User Tools

Site Tools


os_cp:threads

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
os_cp:threads [2025/04/22 22:05] – [Critical sections, deadlocks] jkonczakos_cp:threads [2025/04/25 11:55] (current) – [POSIX condition variables] jkonczak
Line 704: Line 704:
 ===== Critical sections, deadlocks ===== ===== Critical sections, deadlocks =====
  
-~~Exercise.#~~ Download and read through the {{os_cp:threads:another_bad_idea.c}} file. Which lines of code are the critical section? \\ <small>The vital parts of the file is presented below</small>+~~Exercise.#~~ Download and read through the {{os_cp:threads:another_bad_idea.c}} file. Which lines of code are the critical section? \\ <small>The vital parts of the file is presented below.</small>
  
 ~~Exercise.#~~ Spot the deadlock scenario in the code from the previous exercise. ~~Exercise.#~~ Spot the deadlock scenario in the code from the previous exercise.
Line 712: Line 712:
 <html><div style="line-height:1em"></html> <html><div style="line-height:1em"></html>
 <code c> <code c>
-   ⋯ +  … 
-  9│ #define NB_THR 5 +10│ struct myIO {FILE *in; FILE *out;}; 
- 10│ struct myIO {FILE *in; FILE *out;}; +11│ void* threadFunc(void *num); 
- 11│ void* threadFunc(void *num); +  … 
-   ⋯ +17│ struct { 
- 17│ struct { +18│   pthread_mutex_t mtx; 
- 18│   pthread_mutex_t mtx; +19│   char text[256]; 
- 19│   char text[256]; +20│ } item[5]; 
- 20│ } item[5]; +21│ 
- 21│  +22│ int main(int argc, char **argv) { 
- 22│ int main(int argc, char **argv) { +  … 
-   ⋯ +28│   for (intptr_t i = 1; i < 5; ++i) { 
- 28│   for (intptr_t i = 1; i < NB_THR; ++i) { +29│     pthread_t tid; 
- 29│     pthread_t tid; +30│     pthread_create(&tid, NULL, threadFunc, (void *)i); 
- 30│     pthread_create(&tid, NULL, threadFunc, (void *)i); +31│     pthread_detach(tid); 
- 31│     pthread_detach(tid); +32│   } 
- 32│   } +33│   threadFunc(0); 
- 33│   threadFunc(0); +34│ } 
- 34│ } +35│ 
- 35│  +36│ void *threadFunc(void* numRaw) { 
- 36│ void *threadFunc(void* numRaw) { +37│   intptr_t num = (intptr_t) numRaw; 
- 37│   intptr_t num = (intptr_t) numRaw; +38│   struct myIO win = openWin(num); 
- 38│   struct myIO win = openWin(num); +  … 
-   ⋯ +48│   while (1) { 
- 49│   while (1) { +49│     fprintf(win.out, "> "); 
- 50│     char line[1024], nl; +50│ 
- 51│     fprintf(win.out, "> "); +51│     char line[1024]; 
- 53│     fscanf(win.in, "%1023[^\n]%c", line, &nl); +52│     fgets(line, 1024, win.in); 
- 54│   +53│     line[strlen(line)-1] = 0; 
- 55│     int argOne = atoi(line); +54│ 
-   ⋯ +55│     int argOne = atoi(line); 
- 62│     char *argTwoTxt = strchr(line, ' '); +  … 
- 63│   +61│     char *argTwoTxt = strchr(line, ' '); 
- 64│     if (!argTwoTxt) { +62│ 
- 66│       pthread_mutex_lock(&item[argOne].mtx); +63│     if (!argTwoTxt) { 
- 67│       fprintf(win.out, "%d has value: %s\n", argOne, item[argOne].text); +65│       pthread_mutex_lock(&item[argOne].mtx); 
- 69│       pthread_mutex_unlock(&item[argOne].mtx); +66│       fprintf(win.out, "T#%ld reads %d as: %s\n", num, argOne, item[argOne].text); 
- 70│       continue; +67│       pthread_mutex_unlock(&item[argOne].mtx); 
- 71│     } +68│       continue; 
- 72│   +69│     } 
- 73│     argTwoTxt++; +70│ 
- 74│     char *e; +71│     argTwoTxt++; 
- 75│     int argTwo = strtol(argTwoTxt, &e, 10); +72│     char *e; 
- 76│   +73│     int argTwo = strtol(argTwoTxt, &e, 10); 
- 77│     if (!*e && argTwo < 5 && argTwo >= 0 && argOne != argTwo) { +74│ 
- 79│       pthread_mutex_lock(&item[argOne].mtx); +75│     if (!*e && argTwo < 5 && argTwo >= 0 && argOne != argTwo) { 
- 80│       pthread_mutex_lock(&item[argTwo].mtx); +77│       pthread_mutex_lock(&item[argOne].mtx); 
- 81│       fprintf(win.out, "%d gets copied to %d\n", argTwo, argOne); +78│       pthread_mutex_lock(&item[argTwo].mtx); 
- 83│       memcpy(item[argOne].text, item[argTwo].text, sizeof(item[argOne].text)); +79│       fprintf(win.out, "T#%ld copies %d to %d\n", num, argTwo, argOne); 
- 84│       pthread_mutex_unlock(&item[argTwo].mtx); +80│       memcpy(item[argOne].text, item[argTwo].text, sizeof(item[argOne].text)); 
- 85│       pthread_mutex_unlock(&item[argOne].mtx); +81│       pthread_mutex_unlock(&item[argTwo].mtx); 
- 86│     } else { +82│       pthread_mutex_unlock(&item[argOne].mtx); 
- 88│       pthread_mutex_lock(&item[argOne].mtx); +83│     } else { 
- 89│       fprintf(win.out, "%d is set to: %s\n", argOne, argTwoTxt); +85│       pthread_mutex_lock(&item[argOne].mtx); 
- 91│       memset(item[argOne].text, 0, sizeof(item[argOne].text)); +86│       fprintf(win.out, "T#%ld assigns to %d the value: %s\n", num, argOne, argTwoTxt); 
- 92│       strncpy(item[argOne].text, argTwoTxt, sizeof(item[argOne].text) - 1); +87│       memset(item[argOne].text, 0, sizeof(item[argOne].text)); 
- 93│       pthread_mutex_unlock(&item[argOne].mtx); +88│       strncpy(item[argOne].text, argTwoTxt, sizeof(item[argOne].text) - 1); 
- 94│     } +89│       pthread_mutex_unlock(&item[argOne].mtx); 
- 95│   } +90│     } 
- 96│ } +91│   } 
-   ⋯+92│ } 
 +  …
 </code> </code>
 <html></div></html> <html></div></html>
Line 876: Line 877:
 When one thread needs to execute some logic once a specific condition is fulfilled, When one thread needs to execute some logic once a specific condition is fulfilled,
 it should: it should:
 +<html><div style="margin-top:-1.2em"></div></html>
 +<WRAP group>
 +<WRAP half column>
   - lock a mutex,   - lock a mutex,
   - check the condition,   - check the condition,
-  - if the condition is false:+  - while the condition is false:
     - wait on a condition variable,     - wait on a condition variable,
     - go back to step 2,     - go back to step 2,
   - do the logic,   - do the logic,
   - unlock the mutex.   - unlock the mutex.
 +</WRAP>
 +<WRAP half column>
 +<html>
 +<pre class="code c" style="margin-top:-1.4em;margin-bottom:-1.4em;">
 +<span style="opacity:0.66">pthread_mutex_</span>lock<span class="br0">(</span><span class="sy0">&amp;</span>mutex<span class="br0">)</span><span class="sy0">;</span>
 +<span class="kw1">while</span><span class="br0">(</span><span class="sy0">!</span><i>condition</i><span class="br0">)</span>
 +  <span style="opacity:0.66">pthread_cond_</span>wait<span class="br0">(</span><span class="sy0">&amp;</span>condvar<span class="sy0">,</span> <span class="sy0">&amp;</span>mutex<span class="br0">)</span><span class="sy0">;</span>
 +<i>logic<span class="br0">(</span><span class="br0">)</span><span class="sy0">;</span></i>
 +<span style="opacity:0.66">pthread_mutex_</span>unlock<span class="br0">(</span><span class="sy0">&amp;</span>mutex<span class="br0">)</span><span class="sy0">;</span>
 +</pre>
 +</html>
 +</WRAP>
 +</WRAP>
 A thread that may change the state and thus affect the condition should: A thread that may change the state and thus affect the condition should:
 +<html><div style="margin-top:-1.2em"></div></html>
 +<WRAP group>
 +<WRAP half column>
   - lock the mutex,   - lock the mutex,
   - do its logic,   - do its logic,
   - signal the condition variable,   - signal the condition variable,
   - unlock the mutex((One can also signal the condition variable after unlocking the mutex.)).   - unlock the mutex((One can also signal the condition variable after unlocking the mutex.)).
 +</WRAP>
 +<WRAP half column>
 +<html>
 +<pre class="code c" style="padding-top:0; padding-bottom:0; margin-top:-1.4em;margin-bottom:-1.4em;">
 +<span style="opacity:0.66">pthread_mutex_</span>lock<span class="br0">(</span><span class="sy0">&amp;</span>mutex<span class="br0">)</span><span class="sy0">;</span>
 +<i>logic_that_changes_condition<span class="br0">(</span><span class="br0">)</span><span class="sy0">;</span></i>
 +<span style="opacity:0.66">pthread_cond_</span>signal<span class="br0">(</span><span class="sy0">&amp;</span>condvar<span class="br0">)</span><span class="sy0">;</span>
 +<span style="opacity:0.66">pthread_mutex_</span>unlock<span class="br0">(</span><span class="sy0">&amp;</span>mutex<span class="br0">)</span><span class="sy0">;</span>
 +</pre>
 +</html>
 +</WRAP>
 +</WRAP>
  
 <small> <small>
 The example conditions include: The example conditions include:
 +<html><div style="margin-top:-1.2em"></div></html>
   * a boolean flag is set; the flag indicates that another thread finished a part of the computation and the results can used,   * a boolean flag is set; the flag indicates that another thread finished a part of the computation and the results can used,
   * a list of items is not empty; the list contains tasks to be done by this thread,   * a list of items is not empty; the list contains tasks to be done by this thread,
os_cp/threads.1745359551.txt.gz · Last modified: (external edit)