Note that there are some explanatory texts on larger screens.

plurals
  1. POmalloc error in Linux, the same code on Mac OS X runs well
    primarykey
    data
    text
    <p>When I run my code in Mac OS X, it runs fine. However on Linux (Ubuntu), I get the following output:</p> <pre><code>pmichna@pawel-mac:~/alchemists$ ./alchemists 10 Creating 10 alchemists... TESTING_ERROR #0 alchemists: malloc.c:2369: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &amp;((av)-&gt;bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) &amp;&amp; old_size == 0) || ((unsigned long) (old_size) &gt;= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) &amp; ~((2 * (sizeof(size_t))) - 1))) &amp;&amp; ((old_top)-&gt;size &amp; 0x1) &amp;&amp; ((unsigned long)old_end &amp; pagemask) == 0)' failed. make: *** [run] Aborted (core dumped) </code></pre> <p>What's wrong? My code:</p> <pre><code>pmichna@pawel-mac:~/alchemists$ cat alchemists.c #include &lt;pthread.h&gt; #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;unistd.h&gt; #define NUM_APPRENTICES 2 pthread_mutex_t *ingredients_mut; pthread_mutex_t *pots_mut; pthread_cond_t *ingredients_cond; pthread_cond_t *pots_cond; int *ingredients_count; long num_of_pots; long num_of_alchemists; int *pots_usage; // if the pot was used by the alchemist on the right: 1 // if on the left: -1 // if not yet used: 0 void lock_ingredients(long ingredients_index, long tid) { printf("Alchemist #%ld trying to lock ingredients from bowl #%ld...\n", tid, ingredients_index); pthread_mutex_lock(&amp;ingredients_mut[ingredients_index]); if(ingredients_count[ingredients_index]&gt;1) { ingredients_count[ingredients_index]--; printf("Alchemist #%ld took an ingredient from bowl #%ld!\n", tid, ingredients_index); } else { printf("Alchemist #%ld found the bowl #%ld empty. Waiting for the filling apprentice...\n", tid, ingredients_index); pthread_cond_wait(&amp;ingredients_cond[ingredients_index], &amp;ingredients_mut[ingredients_index]); } } void lock_pot(long pot_index, long tid, int expected_pot_value) { printf("Alchemist #%ld trying to lock pot #%ld...\n", tid, pot_index); pthread_mutex_lock(&amp;pots_mut[pot_index]); if(pots_usage[pot_index] == 0 || pots_usage[pot_index] == expected_pot_value) { pots_usage[pot_index] = expected_pot_value; printf("Alchemist #%ld locked pot #%ld!\n", tid, pot_index); } else { printf("Alchemist #%ld found the pot #%ld dirty. :(\n", tid, pot_index); pthread_cond_wait(&amp;pots_cond[pot_index], &amp;pots_mut[pot_index]); printf("Alchemist #%ld now can use the cleaned pot #%ld!\n", tid, pot_index); } } void finish_production(int *gold_produced, long tid, long ingredients_index, long pot_index) { (*gold_produced)++; printf("Alchemist #%ld produced gold!. Current status: %d\n", tid, *gold_produced); pthread_mutex_unlock(&amp;ingredients_mut[ingredients_index]); printf("Alchemist #%ld released the bowl #%ld.\n", tid, ingredients_index); pthread_mutex_unlock(&amp;pots_mut[pot_index]); printf("Alchemist #%ld released the pot #%ld.\n", tid, pot_index); } void alchemist_even_work(long tid, int *gold_produced) // has pot on the left; bowl on the right { long pot_index = tid/2 - 1; long ingredients_index = tid/2; int expected_pot_value = 1; lock_ingredients(ingredients_index, tid); lock_pot(pot_index, tid, expected_pot_value); finish_production(gold_produced, tid, ingredients_index, pot_index); } void alchemist_odd_work(long tid, int *gold_produced) //has pot on the right; bowl on the left { long pot_index = tid/2; long ingredients_index = tid/2; int expected_pot_value = -1; lock_ingredients(ingredients_index, tid); lock_pot(pot_index, tid, expected_pot_value); finish_production(gold_produced, tid, ingredients_index, pot_index); } void alchemist_first_work(long tid, int *gold_produced) // has pot on the left; bowl on the right { long pot_index = num_of_alchemists/2 - 1; long ingredients_index = 0; int expected_pot_value = 1; lock_ingredients(ingredients_index, tid); lock_pot(pot_index, tid, expected_pot_value); finish_production(gold_produced, tid, ingredients_index, pot_index); } void *alchemist_work(void *id) { long tid = (long)id; int sleep_time, gold_produced = 0; printf("Alchemist #%ld started\n", tid); while(gold_produced &lt; 10) { //thinking srand((int)tid); sleep_time = rand()%5+1; printf("Alchemist #%ld going to think %d seconds...\n", tid, sleep_time); sleep(sleep_time); printf("Alchemist #%ld is going to try to make gold!\n", tid); if(tid == 0) { alchemist_first_work(tid, &amp;gold_produced); } else if(tid%2 == 0) { alchemist_even_work(tid, &amp;gold_produced); } else { alchemist_odd_work(tid, &amp;gold_produced); } } printf("Alchemist #%ld going to lunch.\n", tid); pthread_exit(NULL); } void *apprentice_work(void *id) { long tid = (long)id; long i; int sleep_time; switch (tid) { case 0: printf("Cleaning apprentice started.\n"); break; case 1: printf("Ingredients apprentice started.\n"); break; } srand((int)tid); while (1) { sleep_time = rand()%5+1; switch (tid) { case 0: // cleaner of pots printf("Cleaning apprentice going to sleep %d seconds...\n", sleep_time); sleep(sleep_time); printf("Cleaning apprentice is now going to clean all the pots\n"); for(i = 0; i &lt; num_of_pots; i++) { pthread_mutex_lock(&amp;pots_mut[i]); printf("Apprentice cleaning pot #%ld\n", i); pots_usage[i] = 0; pthread_cond_signal(&amp;pots_cond[i]); pthread_mutex_unlock(&amp;pots_mut[i]); } break; case 1: // ingredients printf("Ingredients apprentice going to sleep %d seconds...\n", sleep_time); sleep(sleep_time); printf("Ingredients apprentice going to fill all the pots...\n"); for(i = 0; i &lt; num_of_pots; i++) { pthread_mutex_lock(&amp;ingredients_mut[i]); printf("Apprentice filling bowl #%ld\n", i); ingredients_count[i] = 5; pthread_cond_broadcast(&amp;ingredients_cond[i]); pthread_mutex_unlock(&amp;ingredients_mut[i]); } break; } } pthread_exit(NULL); } int main(int argc, char *argv[]) { long i; num_of_alchemists = atol(argv[1]);; if(num_of_alchemists%2 == 1) { fprintf(stderr, "Only even number of alchemists possible!\n"); exit(1); } num_of_pots = num_of_alchemists/2; // this variable used alse as number of bowls with ingredients pthread_t threads_alchemists[num_of_alchemists]; pthread_t threads_apprentices[NUM_APPRENTICES]; pthread_attr_t attr; ingredients_mut = malloc(num_of_pots*sizeof(pthread_mutex_t)); pots_mut = malloc(num_of_pots*sizeof(pthread_mutex_t)); ingredients_cond = malloc(num_of_pots*sizeof(pthread_cond_t)); ingredients_count = malloc(num_of_pots*sizeof(int)); pots_usage = malloc(num_of_pots*sizeof(int)); pots_cond = malloc(num_of_pots*sizeof(pthread_mutex_t)); for(i = 0; i &lt; num_of_pots; i++) { pthread_mutex_init(&amp;ingredients_mut[i], NULL); pthread_mutex_init(&amp;pots_mut[i], NULL); pthread_cond_init(&amp;ingredients_cond[i], NULL); pthread_cond_init(&amp;pots_cond[i], NULL); ingredients_count[i] = 5; pots_usage[i] = 0; } /* For portability, explicitly create threads in a joinable state */ pthread_attr_init(&amp;attr); pthread_attr_setdetachstate(&amp;attr, PTHREAD_CREATE_JOINABLE); printf("Creating %ld alchemists...\n", num_of_alchemists); for(i = 0; i &lt; num_of_alchemists; i++) { printf("TESTING_ERROR #%ld\n", i); pthread_create(&amp;threads_alchemists[i], &amp;attr, alchemist_work, (void *)i); } for(i = 0; i &lt; NUM_APPRENTICES; i++) { pthread_create(&amp;threads_apprentices[i], &amp;attr, apprentice_work, (void *)i); } /* Wait for all threads to complete */ for (i = 0; i &lt; num_of_alchemists; i++) { pthread_join(threads_alchemists[i], NULL); } printf ("Main(): Waited and joined with %ld alchemist threads.\n", num_of_alchemists); // Clean up pthread_attr_destroy(&amp;attr); for(i = 0; i &lt; num_of_pots; i++) { pthread_mutex_destroy(&amp;ingredients_mut[i]); pthread_mutex_destroy(&amp;pots_mut[i]); pthread_cond_destroy(&amp;ingredients_cond[i]); pthread_cond_destroy(&amp;pots_cond[i]); } free(ingredients_mut); free(ingredients_count); free(ingredients_cond); free(pots_mut); free(pots_usage); free(pots_cond); return 0; } </code></pre> <p>UPDATE:</p> <p>So used valgrind and the program runs, spitting out errors from time to time. What I noticed, they mostly concern conditional variables. One example which appeared just at the beginning:</p> <pre><code>pmichna@pawel-mac:~/alchemists$ valgrind --tool=memcheck ./alchemists 4 ==3552== Memcheck, a memory error detector ==3552== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==3552== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==3552== Command: ./alchemists 4 ==3552== ==3552== Invalid write of size 4 ==3552== at 0x4E3FA32: pthread_cond_init@@GLIBC_2.3.2 (pthread_cond_init.c:33) ==3552== by 0x4018AA: main (in /home/pmichna/alchemists/alchemists) ==3552== Address 0x541a2f8 is 8 bytes after a block of size 80 alloc'd ==3552== at 0x4C2CD7B: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==3552== by 0x4017F4: main (in /home/pmichna/alchemists/alchemists) ==3552== ==3552== Invalid write of size 8 ==3552== at 0x4E3FA41: pthread_cond_init@@GLIBC_2.3.2 (pthread_cond_init.c:40) ==3552== by 0x4018AA: main (in /home/pmichna/alchemists/alchemists) ==3552== Address 0x541a2f0 is 0 bytes after a block of size 80 alloc'd ==3552== at 0x4C2CD7B: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==3552== by 0x4017F4: main (in /home/pmichna/alchemists/alchemists) ==3552== ==3552== Invalid write of size 4 ==3552== at 0x4E3FA57: pthread_cond_init@@GLIBC_2.3.2 (pthread_cond_init.c:42) ==3552== by 0x4018AA: main (in /home/pmichna/alchemists/alchemists) ==3552== Address 0x541a2fc is 12 bytes after a block of size 80 alloc'd ==3552== at 0x4C2CD7B: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==3552== by 0x4017F4: main (in /home/pmichna/alchemists/alchemists) ==3552== Creating 4 alchemists... TESTING_ERROR #0 TESTING_ERROR #1 Alchemist #0 started TESTING_ERROR #2 TESTING_ERROR #3 Alchemist #1 started Alchemist #1 going to think 4 seconds... Alchemist #2 started Alchemist #2 going to think 1 seconds... Alchemist #3 started </code></pre> <p>Does it mean I use the <code>pthread_cond_init</code> function not correctly? How would I fix this?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload