+
+/** ===============================================================
+ * test number 2
+ *
+ * 2 threads flock ops interweave
+ */
+typedef struct {
+ struct flock* lock;
+ int fd;
+} th_data;
+
+void* t2_thread1(void *arg)
+{
+ struct flock *lock = ((th_data *)arg)->lock;
+ int fd = ((th_data *)arg)->fd;
+
+ printf("thread 1: set write lock (blocking)\n");
+ lock->l_type = F_WRLCK;
+ t_fcntl(fd, F_SETLKW, lock);
+ printf("thread 1: set write lock done\n");
+ t_fcntl(fd, F_GETLK, lock);
+ printf("thread 1: unlock\n");
+ lock->l_type = F_UNLCK;
+ t_fcntl(fd, F_SETLK, lock);
+ printf("thread 1: unlock done\n");
+ return 0;
+}
+
+void* t2_thread2(void *arg)
+{
+ struct flock *lock = ((th_data *)arg)->lock;
+ int fd = ((th_data *)arg)->fd;
+
+ sleep(2);
+ printf("thread 2: unlock\n");
+ lock->l_type = F_UNLCK;
+ t_fcntl(fd, F_SETLK, lock);
+ printf("thread 2: unlock done\n");
+ printf("thread 2: set write lock (non-blocking)\n");
+ lock->l_type = F_WRLCK;
+ t_fcntl(fd, F_SETLK, lock);
+ printf("thread 2: set write lock done\n");
+ t_fcntl(fd, F_GETLK, lock);
+ return 0;
+}
+
+int t2(int argc, char* argv[])
+{
+ struct flock lock = {
+ .l_type = F_RDLCK,
+ .l_whence = SEEK_SET,
+ };
+ char file[MAX_PATH_LENGTH] = "";
+ int fd, rc;
+ pthread_t th1, th2;
+ th_data ta;
+
+ snprintf(file, MAX_PATH_LENGTH, "%s/test_t2_file", argv[2]);
+
+ fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
+ if (fd < 0) {
+ fprintf(stderr, "error open file: %s\n", file);
+ return EXIT_FAILURE;
+ }
+
+ t_fcntl(fd, F_SETFL, O_APPEND);
+ if (!(rc = t_fcntl(fd, F_GETFL)) & O_APPEND) {
+ fprintf(stderr, "error get flag: ret %x\n", rc);
+ return EXIT_FAILURE;
+ }
+
+ ta.lock = &lock;
+ ta.fd = fd;
+ rc = pthread_create(&th1, NULL, t2_thread1, &ta);
+ if (rc) {
+ fprintf(stderr, "error create thread 1\n");
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+ rc = pthread_create(&th2, NULL, t2_thread2, &ta);
+ if (rc) {
+ fprintf(stderr, "error create thread 2\n");
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+ (void)pthread_join(th1, NULL);
+ (void)pthread_join(th2, NULL);
+out:
+ t_unlink(file);
+ close(fd);
+ return rc;
+}
+
+/** ==============================================================
+ * program entry
+ */
+void usage(void)
+{
+ fprintf(stderr, "usage: ./flocks_test test# [corresponding arguments]\n");
+}
+
+int main(int argc, char* argv[])
+{
+ int test_no;
+ int rc = EXIT_SUCCESS;
+
+ if (argc < 1) {
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ test_no = atoi(argv[1]);
+
+ switch(test_no) {
+ case 1:
+ rc = t1(argc, argv);
+ break;
+ case 2:
+ rc = t2(argc, argv);
+ break;
+ default:
+ fprintf(stderr, "unknow test number %s\n", argv[1]);
+ break;
+ }
+ return rc;
+}