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){ | ||