int main(void) { char *strw = "set write lock on region", *strr = "set read lock on region"; int fd, bytes_count; fd = open(test_file, O_RDWR|O_CREAT, 0666); /* 開啟檔案 */ if(fd<0) err_exit("Unable to open file"); for (bytes_count = 0; bytes_count<100; bytes_count++) /* 寫入資料 */ write(fd, "A", 1); if (fork()!=0) { /* 父執行緒 */ /* 在區域[10-29]設定共享讀鎖 */ if (SET_LOCK (fd, F_RDLCK, 10, SEEK_SET, 20)<0) fprintf(stderr,"%d %s [10-29] failed\n", getpid(),strr); else fprintf(stderr,"%d %s [10-29] succeed\n",getpid(),strr); /* 在區域[40-49]設定互斥寫鎖 */ if (SET_LOCK (fd, F_WRLCK, 40, SEEK_SET, 10)<0) fprintf(stderr,"%d %s [40-49] failed\n", getpid(),strw); else fprintf(stderr,"%d %s [40-49] succeed \n",getpid(), strw); sleep(3); /* 睡眠3秒以便子執行緒測試鎖 */ printf("%d close file\n",getpid()); close(fd); exit(EXIT_SUCCESS); } else { /* 子執行緒 */ pid_t mypid=getpid(); sleep(1); /* 讓父執行緒先執行 */ /* 對區域[10-14]設定讀鎖,與父執行緒設定的讀鎖部分重疊,可成功 */ if (SET_LOCK (fd, F_RDLCK, 10, SEEK_SET, 5)<0) fprintf(stderr,"%d %s [10-14] failed\n", mypid, strr); else fprintf(stderr, "%d %s [10-14] succeed\n", mypid, strr); /* 對區域[15-20]加寫鎖,與父執行緒設定的讀鎖部分重疊,不會成功 */ if (SET_LOCK (fd, F_WRLCK, 15,SEEK_SET,6)<0) fprintf(stderr,"%d %s [15-20] failed\n", mypid, strw); else fprintf(stderr, "%d %s [15-20]\n", mypid, strw); /* 對區域[40-49]加讀鎖,與父執行緒設定的寫鎖重疊,不會成功 */ if (SET_LOCK (fd, F_RDLCK, 40, SEEK_SET, 10)<0) fprintf(stderr,"%d %s [40-49] failed\n", mypid,strr); else fprintf(stderr,"%d %s [40-49] succeed\n", mypid, strr); /* 對區域[41-60]加寫鎖並等待,與父執行緒設定的寫鎖重疊,等待父執行緒離開後才會成功 */ if (SET_LOCK_W(fd, F_WRLCK, 41, SEEK_SET, 20)<0) fprintf(stderr,"%d %s [41-60] succeed\n", mypid, strw); else fprintf(stderr,"%d %s [41-60] succeed\n", mypid, strw); /* 對區域[0-60]解鎖,將同時釋放區域[10-14]的讀鎖和區域[41-60]的寫鎖 */ if (un_lock (fd,0,SEEK_SET,69)<0) fprintf(stderr,"%d unlock the region [0-69] failed\n", mypid); else fprintf(stderr,"%d unlocked the region [0-69] succeed\n", mypid); fprintf(stderr,"Process %d end\n", mypid); close(fd); exit(EXIT_SUCCESS); } }
int Condition::timed_lock(int microseconds, const char *location) { struct timeval now; struct timespec timeout; int result = 0; #ifndef NO_GUICAST SET_LOCK(this, title, location); #endif pthread_mutex_lock(&mutex); gettimeofday(&now, 0); timeout.tv_sec = now.tv_sec + microseconds / 1000000; timeout.tv_nsec = now.tv_usec * 1000 + (microseconds % 1000000) * 1000; struct timeval start_time; struct timeval new_time; int64_t timeout_msec = ((int64_t)microseconds / 1000); gettimeofday(&start_time, 0); while(value <= 0 && result != ETIMEDOUT) { // This doesn't work in all kernels // result = pthread_cond_timedwait(&cond, &mutex, &timeout); // This is based on the most common frame rate since it's mainly used in // recording. pthread_mutex_unlock(&mutex); usleep(20000); gettimeofday(&new_time, 0); new_time.tv_usec -= start_time.tv_usec; new_time.tv_sec -= start_time.tv_sec; pthread_mutex_lock(&mutex); if(value <= 0 && (int64_t)new_time.tv_sec * 1000 + (int64_t)new_time.tv_usec / 1000 > timeout_msec) result = ETIMEDOUT; } if(result == ETIMEDOUT) { //printf("Condition::timed_lock 1 %s %s\n", title, location); #ifndef NO_GUICAST UNSET_LOCK2 #endif result = 1; } else { //printf("Condition::timed_lock 2 %s %s\n", title, location); #ifndef NO_GUICAST UNSET_LOCK2 #endif if(is_binary) value = 0; else value--; result = 0; } pthread_mutex_unlock(&mutex); return result; }
void EncoderPage::update() { encoder_t _encoders[GUI_NUM_ENCODERS]; USE_LOCK(); SET_LOCK(); m_memcpy(_encoders, Encoders.encoders, sizeof(_encoders)); Encoders.clearEncoders(); CLEAR_LOCK(); for (uint8_t i = 0; i < GUI_NUM_ENCODERS; i++) { if (encoders[i] != NULL) encoders[i]->update(_encoders + i); } }
void Condition::lock(const char *location) { #ifndef NO_GUICAST SET_LOCK(this, title, location); #endif pthread_mutex_lock(&mutex); while(value <= 0) pthread_cond_wait(&cond, &mutex); #ifndef NO_GUICAST UNSET_LOCK2 #endif if(is_binary) value = 0; else value--; pthread_mutex_unlock(&mutex); }
int Mutex::lock(const char *location) { // Test recursive owner and give up if we already own it if(recursive) { pthread_mutex_lock(&recursive_lock); if(thread_id_valid && pthread_self() == thread_id) { count++; pthread_mutex_unlock(&recursive_lock); return 0; } pthread_mutex_unlock(&recursive_lock); } #ifndef NO_GUICAST SET_LOCK(this, title, location); #endif if(pthread_mutex_lock(&mutex)) perror("Mutex::lock"); // Update recursive status for the first lock if(recursive) { pthread_mutex_lock(&recursive_lock); count = 1; thread_id = pthread_self(); thread_id_valid = 1; pthread_mutex_unlock(&recursive_lock); } else { count = 1; } #ifndef NO_GUICAST SET_LOCK2 #endif return 0; }