Re: [patch] fix posix timer errors

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

Thank you for correcting me.

Andrew Morton wrote:
>> diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
>> index 1fc1ea2..479b16b 100644
>> --- a/kernel/posix-cpu-timers.c
>> +++ b/kernel/posix-cpu-timers.c
>> @@ -1477,7 +1477,7 @@ int posix_cpu_nsleep(const clockid_t whi
>>  
>>  	error = do_cpu_nanosleep(which_clock, flags, rqtp, &it);
>>  
>> -	if (error = -ERESTART_RESTARTBLOCK) {
>> +	if (error == -ERESTART_RESTARTBLOCK) {
>>  
>>  	       	if (flags & TIMER_ABSTIME)
>>  			return -ERESTARTNOHAND;
>> @@ -1511,7 +1511,7 @@ long posix_cpu_nsleep_restart(struct res
>>  	restart_block->fn = do_no_restart_syscall;
>>  	error = do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t, &it);
>>  
>> -	if (error = -ERESTART_RESTARTBLOCK) {
>> +	if (error == -ERESTART_RESTARTBLOCK) {
>
> This is the sort of thing which should have been caught in testing, but it
> wasn't, which raises questions about how well-tested the rest of it is?
>
> Plus it will have generated compiler warnings.
>
I'm so sorry that my initial verification was not good enough. I'd tested only
the error cases, which I found. So I didn't catch the mistakes. It's my fault.

Therefore, I did some additional tests with the patches and the mistakes fixed.
I'll re-post the revised patch set later for confirmation.

The test cases are as follows;
 - The timer tests of Open POSIX test suite ver. 1.5.1
 - My initial test cases (Interrupted sleep)
   and some additional test cases (Non-interrupted sleep)

My testcases is inlined at the bottom of this email.

The tested environments are as follows;
 - Hardware: EM64T box
 - Archtechture: x86_64(64bit)
 - Base kernel: vanilla kernel 2.6.18-rc4
 - Distro: FC5
 - Test cases are compiled in both 32bit and 64bit

The test results;
 - Posix test suite
   No regression found. There are still FAILED cases but those are not
   in clock_nanosleep() and not changed with or without the patches.
 - My test cases
   No regression found. And improved in the following cases.
    o 64bit testcase && Interrupted sleep && CLOCK_PROCESS_CPUTIME_ID && !TIMER_ABSTIME
    o 32bit testcase && Interrupted sleep && all clock types && !TIMER_ABSTIME
    o 32bit testcase && Interruptes sleep && CLOCK_PROCESS_CPUTIME_ID && TIMER_ABSTIME

I can provide the test results if you require them.

To use the inlined, compile like this;
 # gcc -lrt -lpthread -DCOMPILE_64 test.c
 or
 # gcc -lrt -lpthread -m32 -DCOMPILE_32 test.c
 and then execute like this;
 # ./a.out 2>/dev/null


Sincerely,
Toyo Abe <[email protected]>

---

#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>

#define NSEC_PER_SEC 1000000000L
#define SLEEPTIME	20	/* in sec */
#define INTERVAL	5	/* in sec */

#ifdef COMPILE_64
#define PRINTFORMAT	"%lld.%09lld"
#else
#define PRINTFORMAT	"%ld.%09ld"
#endif

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void handler(int sig)
{
        printf("Received SIGUSR1\n");
}

void *thread(void *arg)
{
	unsigned long n = 0;

	pthread_mutex_lock(&mutex);
	pthread_cond_signal(&cond);
	pthread_mutex_unlock(&mutex);

	while(1) {
	       	n++;
		/* Without the following stuff, the thread sometimes seems to not be scheduled well. */
		if (!(n %1000000))
			fprintf(stderr, "thread\n");
	}
}

int prepare_thread(pthread_t *tid)
{
	pthread_mutex_lock(&mutex);

	if ( pthread_create(tid, NULL, thread, NULL)) {
		fprintf(stderr, "Fail to create thread.\n");
		return -1;
	}

	pthread_cond_wait(&cond, &mutex);

	return 0;
}

void kill_thread(pthread_t *tid)
{
	pthread_cancel(*tid);
	pthread_mutex_unlock(&mutex);
}

int test_clock_nanosleep(clockid_t which_clock, struct timespec *rqt, struct timespec *rmt,
	       		 struct timespec *now, struct timespec *then, int flags)
{
	pthread_t tid;
	int ret;

	if (which_clock == CLOCK_PROCESS_CPUTIME_ID) {
		if (prepare_thread(&tid))
			return -1;
	}

        clock_gettime(which_clock, then);

        ret = clock_nanosleep(which_clock, flags, rqt, rmt);

        clock_gettime(which_clock, now);

	if (which_clock == CLOCK_PROCESS_CPUTIME_ID)
		kill_thread(&tid);

        return ret;
}

void print_results(const int ret, const struct timespec *rqt, const struct timespec *rmt,
		const struct timespec *now, const struct timespec *then)
{
	long sec = 0;
	long nsec = 0;

        printf("request time = " PRINTFORMAT " [sec]\n", rqt->tv_sec, rqt->tv_nsec);
        printf("remaining time = " PRINTFORMAT " [sec]\n", rmt->tv_sec, rmt->tv_nsec);
        printf("return code = %d\n", ret);

        sec = now->tv_sec - then->tv_sec;
        nsec = now->tv_nsec - then->tv_nsec;

	if (nsec < 0) {
		sec--;
		nsec += NSEC_PER_SEC;
	}

	printf("elapsed time = " PRINTFORMAT " [sec]\n", sec, nsec);

	return;
}

void send_signal(pid_t pid)
{
	/*
         * Parent: send signals to child in the following order.
         * SIGSTOP -> SIGCONT -> SIGUSR1
         */
         sleep(INTERVAL);
         kill(pid, SIGSTOP);
         sleep(1);
         kill(pid, SIGCONT);
         sleep(INTERVAL);
         kill(pid, SIGUSR1);
	return;
}

void init_timespec(clockid_t which_clock, struct timespec *rqt, struct timespec *rmt, int abs)
{
	if (abs)
		clock_gettime(which_clock, rqt);
	else {
		rqt->tv_sec = 0;
		rqt->tv_nsec = 0;
	}

	rqt->tv_sec += SLEEPTIME;
	rmt->tv_sec = 0;
	rmt->tv_nsec = 0;
}

int main(void)
{
        pid_t child;
        struct timespec rqt, rmt;
        struct timespec now, then;
        struct sigaction act;
	clockid_t clockid;
        int ret;

        memset(&act, 0, sizeof(act));
        act.sa_handler = handler;
        sigaction(SIGUSR1, &act, NULL);

	/*
	 * When clockid is
	 * 0: CLOCK_REALTIME
	 * 1: CLOCK_MONOTONIC
	 * 2: CLOCK_PROCESS_CPUTIME_ID
	 */
	for ( clockid=0; clockid < 3; clockid++) {
		char *clockid_str = (clockid==0? "CLOCK_REALTIME" :
				     (clockid==1? "CLOCK_MONOTONIC" :
				      "CLOCK_PROCESS_CPUTIME_ID"));
		int abs;

		/*
		 * When abs is
		 * 0: flags != TIMER_ABSTIME
		 * 1: flags == TIMER_ABSTIME
		 */
		for (abs=0; abs < 2; abs++) {
			int flags = (abs == 1) ? TIMER_ABSTIME : 0;

        		if(child = fork()) {
        		/*
         	 	 * Parent: send signals to child in the following order.
         	 	 * SIGSTOP -> SIGCONT -> SIGUSR1
         	 	 */
				send_signal(child);
                		waitpid(child, NULL, 0);
        		}
        		else {
        		/*
         	 	 * Child: sleep 60 seconds by using clock_nanosleep, but will be interrupted
         	 	 * by SIGUSR1
         	 	 */
				printf("\n[Interrupted Test Case: clock_nanosleep(%s, %s)]\n",
					       	clockid_str, (abs==1? "TIMER_ABSTIME" : "0"));

				init_timespec(clockid, &rqt, &rmt, abs);
				ret = test_clock_nanosleep(clockid, &rqt, &rmt, &now, &then, flags);
				print_results(ret, &rqt, &rmt, &now, &then);

				exit(0);
        		}

			/* Non-interrupted test case */
			printf("\n[Test Case: clock_nanosleep(%s, %s)]\n",
					clockid_str, (abs==1? "TIMER_ABSTIME" : "0"));

			init_timespec(clockid, &rqt, &rmt, abs);
			ret = test_clock_nanosleep(clockid, &rqt, &rmt, &now, &then, flags);
			print_results(ret, &rqt, &rmt, &now, &then);
		}

	}

        return 0;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux