This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
os_cp:2024:prog_assignment [2024/05/21 21:01] jkonczak fixing bugs in example code that uses the library |
os_cp:2024:prog_assignment [2024/06/06 01:38] (current) jkonczak |
||
---|---|---|---|
Line 18: | Line 18: | ||
redundancy will lower the grade. | redundancy will lower the grade. | ||
- | The deadline for the assignment is **02.06.2024** (AoE). Please send the | + | The deadline for the assignment is 02.06.2024 (AoE). Please send the |
solutions to me as an attachment to an e-mail message with the subject | solutions to me as an attachment to an e-mail message with the subject | ||
beginning with ''[OSCP]''. | beginning with ''[OSCP]''. | ||
+ | |||
+ | **The tests that I used to tell if your code behaves as expected are available [[https://www.cs.put.poznan.pl/jkonczak/misc/oscp-prog-check.tar.xz|here]].** | ||
<code c header.h> | <code c header.h> | ||
Line 70: | Line 72: | ||
* The identifiers shall be consecutive numbers starting from 0. | * The identifiers shall be consecutive numbers starting from 0. | ||
* Identifier 0 must always be the main thread. | * Identifier 0 must always be the main thread. | ||
+ | * | ||
+ | * (clarification added on 28 May) thread identifiers must not be | ||
+ | * reused; when a thread with an identifier ID terminates, no new | ||
+ | * thread may get the identifier ID. | ||
* | * | ||
* Each thread must have a message queue in that at most | * Each thread must have a message queue in that at most | ||
Line 186: | Line 192: | ||
#include <stdlib.h> | #include <stdlib.h> | ||
#include <string.h> | #include <string.h> | ||
- | + | ||
struct thread_msg{ | struct thread_msg{ | ||
atomic_int uc; | atomic_int uc; | ||
char * txt; | char * txt; | ||
}; | }; | ||
- | + | ||
thread_msg* thread_msg_make(const char * str); | thread_msg* thread_msg_make(const char * str); | ||
- | + | ||
void t1(void*_); | void t1(void*_); | ||
- | + | ||
void t2(void* arg); | void t2(void* arg); | ||
- | + | ||
int main(){ | int main(){ | ||
thread_init(); | thread_init(); | ||
- | + | | |
// create two more threads | // create two more threads | ||
int id1 = thread_make(t1, NULL); | int id1 = thread_make(t1, NULL); | ||
int id2 = thread_make(t2, (void*)(intptr_t)id1); | int id2 = thread_make(t2, (void*)(intptr_t)id1); | ||
- | + | | |
// send two messages to the first thread | // send two messages to the first thread | ||
thread_msg* msg1 = thread_msg_make("FirstMessage"); | thread_msg* msg1 = thread_msg_make("FirstMessage"); | ||
Line 212: | Line 218: | ||
sprintf(msg2->txt, "%d", id2); | sprintf(msg2->txt, "%d", id2); | ||
thread_send(id1, msg2); | thread_send(id1, msg2); | ||
- | + | | |
// send a message to the second thread | // send a message to the second thread | ||
thread_msg* msg3 = thread_msg_make("Hello "); | thread_msg* msg3 = thread_msg_make("Hello "); | ||
thread_send(id2, msg3); | thread_send(id2, msg3); | ||
- | + | | |
// receive a message from the second thread | // receive a message from the second thread | ||
int sender = id2; | int sender = id2; | ||
Line 222: | Line 228: | ||
thread_gather(&sender, 1, &msg4); | thread_gather(&sender, 1, &msg4); | ||
thread_msg_dec_use_count(msg4); | thread_msg_dec_use_count(msg4); | ||
- | + | | |
return 0; | return 0; | ||
} | } | ||
- | + | ||
void t1(void*_){ | void t1(void*_){ | ||
// receive a message and print its contents | // receive a message and print its contents | ||
Line 233: | Line 239: | ||
printf("%s\n", msg->txt); | printf("%s\n", msg->txt); | ||
thread_msg_dec_use_count(msg); | thread_msg_dec_use_count(msg); | ||
- | + | | |
// receive a message and extract a number (the ID of the second thread) from it | // receive a message and extract a number (the ID of the second thread) from it | ||
thread_receive(&sender, &msg); | thread_receive(&sender, &msg); | ||
Line 239: | Line 245: | ||
sscanf(msg->txt, "%d", &id2); | sscanf(msg->txt, "%d", &id2); | ||
thread_msg_dec_use_count(msg); | thread_msg_dec_use_count(msg); | ||
- | + | | |
// send a message to two threads | // send a message to two threads | ||
int tgt[]={0, id2}; | int tgt[]={0, id2}; | ||
Line 246: | Line 252: | ||
// notice that thread 0 does not retreive the message from the queue | // notice that thread 0 does not retreive the message from the queue | ||
} | } | ||
- | + | ||
void t2(void* arg){ | void t2(void* arg){ | ||
// receive messages from the two threads and output them | // receive messages from the two threads and output them | ||
Line 255: | Line 261: | ||
thread_msg_dec_use_count(msgs[0]); | thread_msg_dec_use_count(msgs[0]); | ||
thread_msg_dec_use_count(msgs[1]); | thread_msg_dec_use_count(msgs[1]); | ||
- | + | | |
// send a message to the main thread | // send a message to the main thread | ||
thread_msg * msg = thread_msg_make(NULL); | thread_msg * msg = thread_msg_make(NULL); | ||
thread_send(0, msg); | thread_send(0, msg); | ||
- | + | | |
thread_term(); | thread_term(); | ||
} | } | ||
- | + | ||
thread_msg* thread_msg_make(const char * str){ | thread_msg* thread_msg_make(const char * str){ | ||
thread_msg* msg = malloc(sizeof(thread_msg)); | thread_msg* msg = malloc(sizeof(thread_msg)); | ||
Line 274: | Line 280: | ||
return msg; | return msg; | ||
} | } | ||
- | + | ||
void thread_msg_inc_use_count(thread_msg* msg){ | void thread_msg_inc_use_count(thread_msg* msg){ | ||
msg->uc++; | msg->uc++; | ||
} | } | ||
- | + | ||
void thread_msg_dec_use_count(thread_msg* msg){ | void thread_msg_dec_use_count(thread_msg* msg){ | ||
if(!--msg->uc){ | if(!--msg->uc){ |