static void check_result (int expected, int actual) { if (expected != actual) log_error ("expected %d, returned %d\n", expected, actual); else log_pass (); }
/* * Check to see that the threads ran in the specified order. */ static void check_run_order (char *order) { const char *sep = ":,"; char *tok, *last, *idstr, *endptr; int expected_id, bytes, count = 0, errors = 0; u_int8_t id; assert ((tok = (char *) malloc (strlen(order) + 1)) != NULL); strcpy (tok, order); /* tok has to be larger than order */ assert (ioctl (pipefd[0], FIONREAD, &bytes) == 0); log_trace ("%d bytes read from FIFO.\n", bytes); for (idstr = strtok_r (tok, sep, &last); (idstr != NULL) && (count < bytes); idstr = strtok_r (NULL, sep, &last)) { /* Get the expected id: */ expected_id = (int) strtol (idstr, &endptr, 10); assert ((endptr != NULL) && (*endptr == '\0')); /* Read the actual id from the pipe: */ assert (read (pipefd[0], &id, sizeof (id)) == sizeof (id)); count = count + sizeof (id); if (id != expected_id) { log_trace ("Thread %d ran out of order.\n", id); errors = errors + 1; } else { log_trace ("Thread %d at priority %d reporting.\n", (int) id, states[id].priority); } } if (count < bytes) { /* Clear the pipe: */ while (count < bytes) { read (pipefd[0], &id, sizeof (id)); count = count + 1; errors = errors + 1; } } else if (bytes < count) errors = errors + count - bytes; if (errors == 0) log_pass (); else log_error ("%d threads ran out of order", errors); }
static void mutex_prioceiling_test (void) { const int test_thread_id = 0; /* ID of test thread */ pthread_mutexattr_t mattr; struct sched_param param; pthread_mutex_t m[3]; mutex_kind_t mkind; int i, ret, policy, my_prio, old_ceiling; log ("Testing priority ceilings\n"); log ("-------------------------\n"); for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { log (" Protype PTHREAD_PRIO_PROTECT, Type %s\n", mutextype_strs[mkind]); /* * Initialize and create a mutex. */ assert (pthread_mutexattr_init (&mattr) == 0); /* Get this threads current priority. */ assert (pthread_getschedparam (pthread_self(), &policy, ¶m) == 0); my_prio = param.sched_priority; /* save for later use */ log_trace ("Current scheduling policy %d, priority %d\n", policy, my_prio); /* * Initialize and create 3 priority protection mutexes with * default (max priority) ceilings. */ assert (pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_PROTECT) == 0); /* * Ensure that the first mutex type is a POSIX * compliant mutex. */ if (mkind != M_POSIX) { assert (pthread_mutexattr_settype (&mattr, mutex_types[mkind]) == 0); } for (i = 0; i < 3; i++) assert (pthread_mutex_init (&m[i], &mattr) == 0); /* * Set the ceiling priorities for the 3 priority protection * mutexes to, 5 less than, equal to, and 5 greater than, * this threads current priority. */ for (i = 0; i < 3; i++) assert (pthread_mutex_setprioceiling (&m[i], my_prio - 5 + 5*i, &old_ceiling) == 0); /* * Check that if we attempt to take a mutex whose priority * ceiling is lower than our priority, we get an error. */ log (" Lock with ceiling priority < thread priority - "); ret = pthread_mutex_lock (&m[0]); check_result (/* expected */ EINVAL, ret); if (ret == 0) pthread_mutex_unlock (&m[0]); /* * Check that we can take a mutex whose priority ceiling * is equal to our priority. */ log (" Lock with ceiling priority = thread priority - "); ret = pthread_mutex_lock (&m[1]); check_result (/* expected */ 0, ret); if (ret == 0) pthread_mutex_unlock (&m[1]); /* * Check that we can take a mutex whose priority ceiling * is higher than our priority. */ log (" Lock with ceiling priority > thread priority - "); ret = pthread_mutex_lock (&m[2]); check_result (/* expected */ 0, ret); if (ret == 0) pthread_mutex_unlock (&m[2]); /* * Have the test thread go into a busy loop for 5 seconds * and see that it doesn't block this thread (since the * priority ceiling of mutex 0 and the priority of the test * thread are both less than the priority of this thread). */ log (" Preemption with ceiling priority < thread " "priority - "); /* Have the test thread take mutex 0. */ send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[0]); sleep (1); log_trace ("Sending busy command.\n"); send_cmd (test_thread_id, CMD_BUSY_LOOP); log_trace ("Busy sent, yielding\n"); pthread_yield (); log_trace ("Returned from yield.\n"); if (states[test_thread_id].flags & (FLAGS_IS_BUSY | FLAGS_WAS_BUSY)) log_error ("test thread inproperly preempted us.\n"); else { /* Let the thread finish its busy loop. */ sleep (6); if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) log_error ("test thread never finished.\n"); else log_pass (); } states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; /* Have the test thread release mutex 0. */ send_cmd (test_thread_id, CMD_RELEASE_ALL); sleep (1); /* * Have the test thread go into a busy loop for 5 seconds * and see that it preempts this thread (since the priority * ceiling of mutex 1 is the same as the priority of this * thread). The test thread should not run to completion * as its time quantum should expire before the 5 seconds * are up. */ log (" Preemption with ceiling priority = thread " "priority - "); /* Have the test thread take mutex 1. */ send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[1]); sleep (1); log_trace ("Sending busy\n"); send_cmd (test_thread_id, CMD_BUSY_LOOP); log_trace ("Busy sent, yielding\n"); pthread_yield (); log_trace ("Returned from yield.\n"); if ((states[test_thread_id].flags & FLAGS_IS_BUSY) == 0) log_error ("test thread did not switch in on yield.\n"); else if (states[test_thread_id].flags & FLAGS_WAS_BUSY) log_error ("test thread ran to completion.\n"); else { /* Let the thread finish its busy loop. */ sleep (6); if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) log_error ("test thread never finished.\n"); else log_pass (); } states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; /* Have the test thread release mutex 1. */ send_cmd (test_thread_id, CMD_RELEASE_ALL); sleep (1); /* * Set the scheduling policy of the test thread to SCHED_FIFO * and have it go into a busy loop for 5 seconds. This * thread is SCHED_RR, and since the priority ceiling of * mutex 1 is the same as the priority of this thread, the * test thread should run to completion once it is switched * in. */ log (" SCHED_FIFO scheduling and ceiling priority = " "thread priority - "); param.sched_priority = states[test_thread_id].priority; assert (pthread_setschedparam (states[test_thread_id].tid, SCHED_FIFO, ¶m) == 0); /* Have the test thread take mutex 1. */ send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[1]); sleep (1); log_trace ("Sending busy\n"); send_cmd (test_thread_id, CMD_BUSY_LOOP); log_trace ("Busy sent, yielding\n"); pthread_yield (); log_trace ("Returned from yield.\n"); if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) { log_error ("test thread did not run to completion.\n"); /* Let the thread finish it's busy loop. */ sleep (6); } else log_pass (); states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; /* Restore the test thread scheduling parameters. */ param.sched_priority = states[test_thread_id].priority; assert (pthread_setschedparam (states[test_thread_id].tid, SCHED_RR, ¶m) == 0); /* Have the test thread release mutex 1. */ send_cmd (test_thread_id, CMD_RELEASE_ALL); sleep (1); /* * Have the test thread go into a busy loop for 5 seconds * and see that it preempts this thread (since the priority * ceiling of mutex 2 is the greater than the priority of * this thread). The test thread should run to completion * and block this thread because its active priority is * higher. */ log (" SCHED_FIFO scheduling and ceiling priority > " "thread priority - "); /* Have the test thread take mutex 2. */ send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[2]); sleep (1); log_trace ("Sending busy\n"); send_cmd (test_thread_id, CMD_BUSY_LOOP); log_trace ("Busy sent, yielding\n"); pthread_yield (); log_trace ("Returned from yield.\n"); if ((states[test_thread_id].flags & FLAGS_IS_BUSY) != 0) { log_error ("test thread did not run to completion.\n"); /* Let the thread finish it's busy loop. */ sleep (6); } else if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) log_error ("test thread never finished.\n"); else log_pass (); states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; /* Have the test thread release mutex 2. */ send_cmd (test_thread_id, CMD_RELEASE_ALL); sleep (1); /* Destroy the mutexes. */ for (i = 0; i < 3; i++) assert (pthread_mutex_destroy (&m[i]) == 0); } }
void main(int argc, char *argv[]) { int i, ret, fd; char *penv[] = {"mnt", "test_file"}; log_assert("Verify access time will be changed when file data" \ "was last accessed."); log_onexit(cleanup); /* * Get envirnment variable value */ /* for (i = 0; i < sizeof (penv) / sizeof (char *); i++) { if ((penv[i] = getenv(penv[i])) == NULL) { log_must(-1, "getenv(penv[i])"); } }*/ (void) snprintf(tfile, sizeof (tfile), "%s/%s", "/tank/zfs","test_file"); /* * If the test file is existing, remove it firstly */ printf("file : %s\n", tfile); if (access(tfile, F_OK) == 0) { unlink(tfile); } ret = 0; if ((fd = open(tfile, O_WRONLY | O_CREAT | O_TRUNC, ALL_MODE)) == -1) { ret = errno; } if (fd != -1) { (void) close(fd); } (void) snprintf(msg, sizeof (msg), \ "open(%s, O_WRONLY | O_CREAT | O_TRUNC, ALL_MODE)", tfile); log_must(ret, msg); for (i = 5; i < NCOMMAND; i++) { time_t t1, t2; /* * Get original time before operating. */ ret = get_file_time(tfile, timetest_table[i].type, &t1); if (ret != 0) { (void) snprintf(msg, sizeof (msg), "get_file_time(%s, %d, &t1)", tfile, timetest_table[i].type); log_must(ret, msg); } /* * Sleep 2 seconds, then invoke command on givin file */ sleep(2); timetest_table[i].func(tfile); /* * Get time after operating. */ ret = get_file_time(tfile, timetest_table[i].type, &t2); if (ret != 0) { (void) snprintf(msg, sizeof (msg), "get_file_time(%s, %d, &t2)", tfile, timetest_table[i].type); log_must(ret, msg); } if (t1 == t2) { snprintf(msg, sizeof (msg), "%s: t1(%ld) == t2(%ld)", timetest_table[i].name, (long)t1, (long)t2); log_must(-1, msg); } else { snprintf(msg, sizeof (msg), "%s: t1(%ld) != t2(%ld)", timetest_table[i].name, (long)t1, (long)t2); log_must(0, msg); } } (void) unlink(tfile); log_pass("Verify access time will be changed passed."); }