0

リンクリストの各ノードには、value作業が必要なaとworker、リストで作業するスレッドの番号が含まれています。リストで機能するはずのリスト要素とスレッドの数は、コマンドラインパラメーター(argv[1]とargv[2])です。しかし、どういうわけか、ホールプロセスで、私のリストの最後のノードが評価/機能しません。私が考えた修正は、スレッド関数でdo {} while();を使用することです。それを評価するための構造ですが、機能しませんでした。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <math.h>   

#define workTime 5
#define workersLimitNr 3

struct dataBlock{
    struct node *root;
    int listSize;
    int forIndex;
};

struct node { // std linked list node
    int value;
    int worker;
    struct node *next;
};

int slots = 0; // only 3 threads are allowed to access the list
int availableCheck(){   // check if thread can acces the list
    if(slots < 3) return 0;
    else return -1;
}

pthread_mutex_t mutp = PTHREAD_MUTEX_INITIALIZER;   //condvar mutex
pthread_cond_t  condvar = PTHREAD_COND_INITIALIZER;   //condvar

void * worker( void *data ){
    int j;
    struct dataBlock *inData = (struct dataBlock *) data;
    struct node *root = inData->root;
    int listSize =  inData->listSize;
    int forIndex = inData ->forIndex;
    free(data);
    printf( "*    Thread id: %lu    forID:  %d  workerNode: \n",pthread_self(),forIndex); 

    pthread_mutex_lock( &mutp );
    if(availableCheck() < 0){
        printf( " ^^^ List not available yet... \n" ); 
        pthread_cond_wait( &condvar, &mutp );
    } 
    struct node *it = root;

    printf( "_ _ _ _forID_ %d\n", forIndex );
    do{
        if(forIndex == it->worker){
            printf("valid for sqrt  forIndex %d == it->worker %d\n",forIndex, it->worker );
            if(it->value > 2){
                while(it->value != 1)
                it->value = sqrt(it->value);
                // it->value = it->value - 1;
            }
        }
        it = it->next;
        printf("->val: %d   \n", it->value);
    }while(it->next !=  NULL);

    pthread_cond_signal( &condvar ); // 
    pthread_mutex_unlock( &mutp ); 
    return NULL;
}

int main( int argc, char *argv[] ){
    if ( argc != 3 ){
        printf( "Programm must be called with \n NR of elements and NR of workers! \n " );
        exit( 1 );
    }

    int i;
    struct node *root;
    struct node *iterator;  

//prepare list for task
    int listSize = atoi(argv[1]);
    int nrWorkers = atoi(argv[2]);
    root = malloc(sizeof( struct node) );

    root->value = rand() % 100;
    root->worker = 0;
    iterator = root;

    for( i=1; i<listSize; i++ ){
        iterator->next = malloc(sizeof(struct node));
        iterator = iterator->next;
        iterator->value = rand() % 100;
        iterator->worker = i % nrWorkers;
        printf("node #%d worker: %d  value: %d\n", i, iterator->worker,iterator->value);
    }
    printf("? List got populated\n");

// Create all threads to parse the link list
    int ret;    
    printf("workersInput: %d\n",nrWorkers);
    pthread_mutex_init(&mutp,NULL);

    pthread_t w_thread;
    pthread_t* w_threads = malloc(nrWorkers * sizeof(w_thread));


    for( i=0; i < nrWorkers; i++ ){         
        struct dataBlock *data = malloc(sizeof(struct dataBlock));
        data->root = root;
        data->listSize = listSize;
        data->forIndex = i;
        ret = pthread_create ( &w_threads[i], NULL, worker, (void *) data );
        if( ret ) {
            perror("Thread creation fail");
            exit(2);    
        }   
        printf("in for, ret= %d\n",ret);

    } 

    for ( i = 0; i < nrWorkers; i++){
        pthread_join(w_threads[i],NULL);
    }
    iterator = root;
    for ( i = 0; i < listSize; i++){
        printf("val: %d  worker: %d _  ", iterator->value, iterator->worker);
        iterator = iterator->next;
    }

    free(root);
    free(iterator);
    return 0;
}

valgrind -vを編集します:

bogdan@bogdan-VirtualBox:~/dos/threads$ valgrind -v ./s 2 2
==7205== Memcheck, a memory error detector
==7205== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==7205== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==7205== Command: ./s 2 2
==7205== 
--7205-- Valgrind options:
--7205--    --suppressions=/usr/lib/valgrind/debian-libc6-dbg.supp
--7205--    -v
--7205-- Contents of /proc/version:
--7205--   Linux version 3.2.0-34-generic-pae (buildd@roseapple) (gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) ) #53-Ubuntu SMP Thu Nov 15 11:11:12 UTC 2012
--7205-- Arch and hwcaps: X86, x86-sse1-sse2
--7205-- Page sizes: currently 4096, max supported 4096
--7205-- Valgrind library directory: /usr/lib/valgrind
--7205-- Reading syms from /lib/i386-linux-gnu/ld-2.15.so (0x4000000)
--7205--   Considering /lib/i386-linux-gnu/ld-2.15.so ..
--7205--   .. CRC mismatch (computed 405891ab wanted 9a1d2f37)
--7205--   Considering /usr/lib/debug/lib/i386-linux-gnu/ld-2.15.so ..
--7205--   .. CRC is valid
--7205-- Reading syms from /home/bogdan/dos/threads/s (0x8048000)
--7205-- Reading syms from /usr/lib/valgrind/memcheck-x86-linux (0x38000000)
--7205--   Considering /usr/lib/valgrind/memcheck-x86-linux ..
--7205--   .. CRC mismatch (computed 169814b3 wanted aeba1395)
--7205--    object doesn't have a symbol table
--7205--    object doesn't have a dynamic symbol table
--7205-- Reading suppressions file: /usr/lib/valgrind/debian-libc6-dbg.supp
--7205-- Reading suppressions file: /usr/lib/valgrind/default.supp
==7205== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-7205-by-bogdan-on-???
==7205== embedded gdbserver: writing to   /tmp/vgdb-pipe-to-vgdb-from-7205-by-bogdan-on-???
==7205== embedded gdbserver: shared mem   /tmp/vgdb-pipe-shared-mem-vgdb-7205-by-bogdan-on-???
==7205== 
==7205== TO CONTROL THIS PROCESS USING vgdb (which you probably
==7205== don't want to do, unless you know exactly what you're doing,
==7205== or are doing some strange experiment):
==7205==   /usr/lib/valgrind/../../bin/vgdb --pid=7205 ...command...
==7205== 
==7205== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==7205==   /path/to/gdb ./s
==7205== and then give GDB the following command
==7205==   target remote | /usr/lib/valgrind/../../bin/vgdb --pid=7205
==7205== --pid is optional if only one valgrind process is running
==7205== 
--7205-- REDIR: 0x40182d0 (strlen) redirected to 0x38056b04 (???)
--7205-- REDIR: 0x4018050 (index) redirected to 0x38056adf (???)
--7205-- Reading syms from /usr/lib/valgrind/vgpreload_core-x86-linux.so (0x4025000)
--7205--   Considering /usr/lib/valgrind/vgpreload_core-x86-linux.so ..
--7205--   .. CRC mismatch (computed 79fe1296 wanted 94e37e32)
--7205--    object doesn't have a symbol table
--7205-- Reading syms from /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so (0x4028000)
--7205--   Considering /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so ..
--7205--   .. CRC mismatch (computed 85cd0163 wanted d1841711)
--7205--    object doesn't have a symbol table
--7205-- Reading syms from /lib/i386-linux-gnu/libm-2.15.so (0x4047000)
--7205--   Considering /lib/i386-linux-gnu/libm-2.15.so ..
--7205--   .. CRC mismatch (computed 6ee9373d wanted 98815fe2)
--7205--   Considering /usr/lib/debug/lib/i386-linux-gnu/libm-2.15.so ..
--7205--   .. CRC is valid
--7205-- Reading syms from /lib/i386-linux-gnu/libpthread-2.15.so (0x4073000)
--7205--   Considering /lib/i386-linux-gnu/libpthread-2.15.so ..
--7205--   .. CRC mismatch (computed e3e38d22 wanted 86ccdb6e)
--7205--   Considering /usr/lib/debug/lib/i386-linux-gnu/libpthread-2.15.so ..
--7205--   .. CRC is valid
--7205-- Reading syms from /lib/i386-linux-gnu/libc-2.15.so (0x408e000)
--7205--   Considering /lib/i386-linux-gnu/libc-2.15.so ..
--7205--   .. CRC mismatch (computed 75ebd58c wanted bfe81264)
--7205--   Considering /usr/lib/debug/lib/i386-linux-gnu/libc-2.15.so ..
--7205--   .. CRC is valid
--7205-- REDIR: 0x410bf70 (strnlen) redirected to 0x40254a0 (_vgnU_ifunc_wrapper)
--7205-- REDIR: 0x410d4c0 (strncasecmp) redirected to 0x40254a0 (_vgnU_ifunc_wrapper)
--7205-- REDIR: 0x4124fb0 (strstr) redirected to 0x40254a0 (_vgnU_ifunc_wrapper)
--7205-- REDIR: 0x4124bf0 (__GI_strstr) redirected to 0x402f030 (strstr)
--7205-- REDIR: 0x410c110 (__GI_strrchr) redirected to 0x402c1b0 (__GI_strrchr)
--7205-- REDIR: 0x4107d70 (malloc) redirected to 0x402be00 (malloc)
--7205-- REDIR: 0x410e7e0 (strchrnul) redirected to 0x402ebe0 (strchrnul)
node #1 worker: 1  value: 86
--7205-- REDIR: 0x4108250 (free) redirected to 0x402b000 (free)
--7205-- REDIR: 0x410beb0 (__GI_strlen) redirected to 0x402c670 (__GI_strlen)
? List got populated
workersInput: 2
--7205-- REDIR: 0x4108d30 (calloc) redirected to 0x402a540 (calloc)
in for, ret= 0
*    Thread id: 82025280    forID:  0  workerNode: 
in for, ret= 0
*    Thread id: 90417984    forID:  1  workerNode: 
_ _ _ _forID_ 1
->val: 86   
valid for sqrt  forIndex 1 == it->worker 1
==7205== Thread 3:
==7205== Invalid read of size 4
==7205==    at 0x804892E: worker (in /home/bogdan/dos/threads/s)
==7205==    by 0x4079D4B: start_thread (pthread_create.c:308)
==7205==    by 0x417CD3D: clone (clone.S:130)
==7205==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==7205== 
==7205== 
==7205== Process terminating with default action of signal 11 (SIGSEGV)
==7205==  Access not within mapped region at address 0x0
==7205==    at 0x804892E: worker (in /home/bogdan/dos/threads/s)
==7205==    by 0x4079D4B: start_thread (pthread_create.c:308)
==7205==    by 0x417CD3D: clone (clone.S:130)
==7205==  If you believe this happened as a result of a stack
==7205==  overflow in your program's main thread (unlikely but
==7205==  possible), you can try to increase the size of the
==7205==  main thread stack using the --main-stacksize= flag.
==7205==  The main thread stack size used in this run was 8388608.
==7205== 
==7205== HEAP SUMMARY:
==7205==     in use at exit: 304 bytes in 5 blocks
==7205==   total heap usage: 7 allocs, 2 frees, 328 bytes allocated
==7205== 
==7205== Searching for pointers to 5 not-freed blocks
==7205== Checked 16,847,500 bytes
==7205== 
==7205== LEAK SUMMARY:
==7205==    definitely lost: 0 bytes in 0 blocks
==7205==    indirectly lost: 0 bytes in 0 blocks
==7205==      possibly lost: 272 bytes in 2 blocks
==7205==    still reachable: 32 bytes in 3 blocks
==7205==         suppressed: 0 bytes in 0 blocks
==7205== Rerun with --leak-check=full to see details of leaked memory
==7205== 
==7205== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==7205== 
==7205== 1 errors in context 1 of 1:
==7205== Invalid read of size 4
==7205==    at 0x804892E: worker (in /home/bogdan/dos/threads/s)
==7205==    by 0x4079D4B: start_thread (pthread_create.c:308)
==7205==    by 0x417CD3D: clone (clone.S:130)
==7205==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==7205== 
==7205== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Killed
4

2 に答える 2

1

問題は、ワーカースレッドループの終了条件です

while(it->next !=  NULL);

最後のリストアイテムを処理しようとすると終了します。これをに変更すると、うまくいくはずです

while(it !=  NULL);

代わりは。

リストの設定にもエラーがあるのではないかと思います。最後の要素のnextメンバーが初期化されたことはありますか?これに対処する方法はいくつかありますが、最も侵襲性が低いのは、リスト設定の最後に設定iterator->nextすることです。NULL

for( i=1; i<listSize; i++ ){
    iterator->next = malloc(sizeof(struct node));
    iterator = iterator->next;
    iterator->value = rand() % 100;
    iterator->worker = i % nrWorkers;
    printf("node #%d worker: %d  value: %d\n", i, iterator->worker,iterator->value);
}
iterator->next = NULL;
于 2012-12-03T10:49:44.137 に答える
0

常に条件付き待機をwhile(condition)に置きます。

私がこれをしたとき、それは私にとってうまくいきます。もちろん、mallocの戻り値とその他のマイナーなバグ修正をすべてキャストする必要がありました。

while(availableCheck() < 0)
{
   printf( " ^^^ List not available yet... \n" ); 
   pthread_cond_wait( &condvar, &mutp );
} 
于 2016-03-28T05:06:50.910 に答える