#define _GNU_SOURCE #include #include #include #include #include #include #include #include typedef unsigned int uint; typedef struct _LOCK { uint num; pid_t tid; } LOCK; void LockSiData( LOCK *shared ) { pid_t tid = gettid(); uint const yield = 4; uint i; /* struct timespec ts = {0}; ts.tv_nsec = 1; */ while ( shared->tid != tid ) { if ( !(shared->tid) ) shared->tid = tid; //clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, 0); for ( i = 0; i < yield; ++i ) sched_yield(); } shared->num++; } void FreeSiData( LOCK *shared ) { pid_t tid = gettid(); if ( shared->tid != tid ) return; shared->num--; if ( shared->num ) return; shared->tid = (pid_t)0; //sched_yield(); } volatile uint quit = 0; volatile uint data = 0; LOCK lock = {0}; void* thread( void *ud ) { uint i; struct timespec ts = {0}; ts.tv_nsec = 1; (void)ud; while ( quit < CLOCKS_PER_SEC ) { LockSiData( &lock ); i = data++; if (i != 0) { flockfile( stdout ); printf("var = %u, expected 0\n", i); funlockfile( stdout ); FreeSiData( &lock ); exit(1); } /* Why is needed for the test? */ clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, 0); i = data--; if (i != 1) { flockfile( stdout ); printf("var = %u, expected 1\n", i); funlockfile( stdout ); FreeSiData( &lock ); exit(1); } ++quit; FreeSiData( &lock ); } return ud; } int main() { pthread_t pt; int i; for (i = 0; i < 2; i++) { if ((errno = pthread_create(&pt, 0, thread, 0)) != 0 ) { flockfile( stdout ); printf("pthread_create failed: %m\n"); funlockfile( stdout ); return 1; } } pthread_exit(0); }