コード例 #1
0
ファイル: susp.cpp プロジェクト: keyz182/BOINC-7.0
/*
 * Dynamically initialize the "suspend package" when first used
 * (called by pthread_once).
 */
void
suspend_init_routine (void)
{
    int status;
    struct sigaction sigusr1, sigusr2;

    /*
     * Initialize a semaphore, to be used by the signal handler to
     * confirm suspension. We only need one, because suspend & resume
     * are fully serialized by a mutex.
     */
    status = sem_init (&sem, 0, 1);
    if (status == -1)
        errno_abort ("Initializing semaphore");

    /*
     * Allocate the suspended threads array. This array is used to guarantee
     * idempotency.
     */
    bottom = 10;
    array = (Victim_t*) calloc (bottom, sizeof (Victim_t));

    /*
     * Install the signal handlers for suspend/resume.
     *
     * We add SIGUSR2 to the sa_mask field for the SIGUSR1 handler. That
     * avoids a race if one thread suspends the target while another resumes
     * that same target. (The SIGUSR2 signal cannot be delivered before the
     * target thread calls sigsuspend.)
     */
    sigusr1.sa_flags = 0;
    sigusr1.sa_handler = suspend_signal_handler;
    sigemptyset (&sigusr1.sa_mask);
    sigaddset (&sigusr1.sa_mask, SIGUSR2);

    sigusr2.sa_flags = 0;
    sigusr2.sa_handler = resume_signal_handler;
    sigemptyset (&sigusr2.sa_mask);

    status = sigaction (SIGUSR1, &sigusr1, NULL);
    if (status == -1)
        errno_abort ("Installing suspend handler");
    
    status = sigaction (SIGUSR2, &sigusr2, NULL);
    if (status == -1)
        errno_abort ("Installing resume handler");
    
    return;
}
コード例 #2
0
ファイル: alarm_fork.c プロジェクト: githubzenganiu/toekn
int main (int argc, char *argv[])
{
    int status;
    char line[128];
    int seconds;
    pid_t pid;
    char message[64];

    while (1) {
        printf ("Alarm> ");
        if (fgets (line, sizeof (line), stdin) == NULL) 
			exit (0);
        if (strlen (line) <= 1) 
			continue;

        /*
         * Parse input line into seconds (%d) and a message
         * (%64[^\n]), consisting of up to 64 characters
         * separated from the seconds by whitespace.
         */
        if (sscanf (line, "%d %64[^\n]", 
            &seconds, message) < 2) {
            fprintf (stderr, "Bad command\n");
        } else {
            pid = fork ();
            if (pid == (pid_t)-1)
                errno_abort ("Fork");
            if (pid == (pid_t)0) {
                /*
                 * If we're in the child, wait and then print a message
                 */
                sleep (seconds);
                printf ("(%d) %s\n", seconds, message);
                exit (0);
            } else {
                /*
                 * In the parent, call waitpid() to collect any children that
                 * have already terminated.
                 */
                do {
                    pid = waitpid ((pid_t)-1, NULL, WNOHANG);//cast -1 as the type of pid_t
                    if (pid == (pid_t)-1)
                        errno_abort ("Wait for child");
                } while (pid != (pid_t)0);
            }
        }
    }
}
コード例 #3
0
ファイル: workq_main.c プロジェクト: 1023xp/training
/*
 * Thread start routine that issues work queue requests.
 */
void *thread_routine (void *arg)
{
    power_t *element;
    int count;
    unsigned int seed = (unsigned int)time (NULL);
    int status;

    /*
     * Loop, making requests.
     */
    for (count = 0; count < ITERATIONS; count++) {
        element = (power_t*)malloc (sizeof (power_t));
        if (element == NULL)
            errno_abort ("Allocate element");
        element->value = rand_r (&seed) % 20;
        element->power = rand_r (&seed) % 7;
        DPRINTF ((
            "Request: %d^%d\n",
            element->value, element->power));
        status = workq_add (&workq, (void*)element);
        if (status != 0)
            err_abort (status, "Add to work queue");
        sleep (rand_r (&seed) % 5);
    }
    return NULL;
}
コード例 #4
0
ファイル: alarm_thread.c プロジェクト: 1023xp/training
int main (int argc, char *argv[])
{
    int status;
    char line[128];
    alarm_t *alarm;
    pthread_t thread;

    while (1) {
        printf ("Alarm> ");
        if (fgets (line, sizeof (line), stdin) == NULL) exit (0);
        if (strlen (line) <= 1) continue;
        alarm = (alarm_t*)malloc (sizeof (alarm_t));
        if (alarm == NULL)
            errno_abort ("Allocate alarm");

        /*
         * Parse input line into seconds (%d) and a message
         * (%64[^\n]), consisting of up to 64 characters
         * separated from the seconds by whitespace.
         */
        if (sscanf (line, "%d %64[^\n]", 
            &alarm->seconds, alarm->message) < 2) {
            fprintf (stderr, "Bad command\n");
            free (alarm);
        } else {
            status = pthread_create (
                &thread, NULL, alarm_thread, alarm);
            if (status != 0)
                err_abort (status, "Create alarm thread");
        }
    }
}
コード例 #5
0
ファイル: pipe.c プロジェクト: chackotemp/codetestmap
/*
 * External interface to create a pipeline. All the
 * data is initialized and the threads created. They'll
 * wait for data.
 */
int pipe_create (pipe_t *pipe, int stages)
{
    int pipe_index;
    stage_t **link = &pipe->head, *new_stage, *stage;
    int status;

    status = pthread_mutex_init (&pipe->mutex, NULL);
    if (status != 0)
        err_abort (status, "Init pipe mutex");
    pipe->stages = stages;
    pipe->active = 0;

    for (pipe_index = 0; pipe_index <= stages; pipe_index++) {
        new_stage = (stage_t*)malloc (sizeof (stage_t));
        if (new_stage == NULL)
            errno_abort ("Allocate stage");
        status = pthread_mutex_init (&new_stage->mutex, NULL);
        if (status != 0)
            err_abort (status, "Init stage mutex");
        status = pthread_cond_init (&new_stage->avail, NULL);
        if (status != 0)
            err_abort (status, "Init avail condition");
        status = pthread_cond_init (&new_stage->ready, NULL);
        if (status != 0)
            err_abort (status, "Init ready condition");
        new_stage->data_ready = 0;
        *link = new_stage;
        link = &new_stage->next;
    }

    *link = (stage_t*)NULL;     /* Terminate list */
    pipe->tail = new_stage;     /* Record the tail */

    /*
     * Create the threads for the pipe stages only after all
     * the data is initialized (including all links). Note
     * that the last stage doesn't get a thread, it's just
     * a receptacle for the final pipeline value.
     *
     * At this point, proper cleanup on an error would take up
     * more space than worthwhile in a "simple example", so
     * instead of cancelling and detaching all the threads
     * already created, plus the synchronization object and
     * memory cleanup done for earlier errors, it will simply
     * abort.
     */
    for (   stage = pipe->head;
            stage->next != NULL;
            stage = stage->next) {
        status = pthread_create (
            &stage->thread, NULL, pipe_stage, (void*)stage);
        if (status != 0)
            err_abort (status, "Create pipe stage");
    }
    return 0;
}
コード例 #6
0
ファイル: alarm_cond.c プロジェクト: cumirror/pthread
int main(int argc,char* argv[])
{
	int status;
	char line[128];
	alarm_t* alarm;
	pthread_t thread;
	status=pthread_create(&thread,NULL,alarm_thread,NULL);
	if(status!=0)
	{
				err_abort(status,"Create alarm thread");						
	}
	while(1){
		printf("Alarm> \n");
		if(fgets(line,sizeof(line),stdin)==NULL) exit(0);
		if(strlen(line)<=1) continue;
		alarm=(alarm_t*)malloc(sizeof(alarm_t));
		if(alarm==NULL)
		{
			errno_abort("Allocate alarm");		
		}
		if(sscanf(line,"%d %64[^\n]",
			&alarm->seconds,alarm->message)<2)
		{
			fprintf(stderr,"Bad command\n");
			free(alarm);
		}
		else
		{
			status=pthread_mutex_lock(&alarm_mutex);
			if(status!=0)
			{
				err_abort(status,"Lock mutex");
			}
			alarm->time=time(NULL)+alarm->seconds;
			alarm_insert(alarm);
			status=pthread_mutex_unlock(&alarm_mutex);
			if(status!=0)
			{
				err_abort(status,"Unlock mutex");
			}
		}
	}	
	return 0;
}
コード例 #7
0
ファイル: flock.c プロジェクト: abo321/PosixThreads
/*
 * This routine writes a prompt to stdout (passed as the thread's
 * "arg"), and reads a response. All other I/O to stdin and stdout
 * is prevented by the file locks until both prompt and fgets are
 * complete.
 */
void *prompt_routine (void *arg)
{
    char *prompt = (char*)arg;
    char *string;
    int len;

    string = (char*)malloc (128);
    if (string == NULL)
        errno_abort ("Alloc string");
    flockfile (stdin);
    flockfile (stdout);
    printf (prompt);
    if (fgets (string, 128, stdin) == NULL)
        string[0] = '\0';
    else {
        len = strlen (string);
        if (len > 0 && string[len-1] == '\n')
            string[len-1] = '\0';
    }
    funlockfile (stdout);
    funlockfile (stdin);
    return (void*)string;
}
コード例 #8
0
/*
 * Thread start routine that uses pthread_once to dynamically
 * create a thread-specific data key.
 */
void *thread_routine (void *arg)
{
    tsd_t *value;
    int status;

    status = pthread_once (&key_once, once_routine);
    if (status != 0)
        err_abort (status, "Once init");
    value = (tsd_t*)malloc (sizeof (tsd_t));
    if (value == NULL)
        errno_abort ("Allocate key value");
    status = pthread_setspecific (tsd_key, value);
    if (status != 0)
        err_abort (status, "Set tsd");
    printf ("%s set tsd value %p\n", arg, value);
    value->thread_id = pthread_self ();
    value->string = (char*)arg;
    value = (tsd_t*)pthread_getspecific (tsd_key);
    printf ("%s starting...\n", value->string);
    sleep (2);
    value = (tsd_t*)pthread_getspecific (tsd_key);
    printf ("%s done...\n", value->string);
    return NULL;
}
コード例 #9
0
ファイル: crew.c プロジェクト: 1023xp/training
/*
 * The thread start routine for crew threads. Waits until "go"
 * command, processes work items until requested to shut down.
 */
void *worker_routine (void *arg)
{
    worker_p mine = (worker_t*)arg;
    crew_p crew = mine->crew;
    work_p work, new_work;
    struct stat filestat;
    struct dirent *entry;
    int status;

    /*
     * "struct dirent" is funny, because POSIX doesn't require
     * the definition to be more than a header for a variable
     * buffer. Thus, allocate a "big chunk" of memory, and use
     * it as a buffer.
     */
    entry = (struct dirent*)malloc (
        sizeof (struct dirent) + name_max);
    if (entry == NULL)
        errno_abort ("Allocating dirent");
    
    status = pthread_mutex_lock (&crew->mutex);
    if (status != 0)
        err_abort (status, "Lock crew mutex");

    /*
     * There won't be any work when the crew is created, so wait
     * until something's put on the queue.
     */
    while (crew->work_count == 0) {
        status = pthread_cond_wait (&crew->go, &crew->mutex);
        if (status != 0)
            err_abort (status, "Wait for go");
    }

    status = pthread_mutex_unlock (&crew->mutex);
    if (status != 0)
        err_abort (status, "Unlock mutex");

    DPRINTF (("Crew %d starting\n", mine->index));

    /*
     * Now, as long as there's work, keep doing it.
     */
    while (1) {
        /*
         * Wait while there is nothing to do, and
         * the hope of something coming along later. If
         * crew->first is NULL, there's no work. But if
         * crew->work_count goes to zero, we're done.
         */
        status = pthread_mutex_lock (&crew->mutex);
        if (status != 0)
            err_abort (status, "Lock crew mutex");

        DPRINTF (("Crew %d top: first is %#lx, count is %d\n",
                  mine->index, crew->first, crew->work_count));
        while (crew->first == NULL) {
            status = pthread_cond_wait (&crew->go, &crew->mutex);
            if (status != 0)
                err_abort (status, "Wait for work");
        }

        DPRINTF (("Crew %d woke: %#lx, %d\n",
                  mine->index, crew->first, crew->work_count));

        /*
         * Remove and process a work item
         */
        work = crew->first;
        crew->first = work->next;
        if (crew->first == NULL)
            crew->last = NULL;

        DPRINTF (("Crew %d took %#lx, leaves first %#lx, last %#lx\n",
                  mine->index, work, crew->first, crew->last));

        status = pthread_mutex_unlock (&crew->mutex);
        if (status != 0)
            err_abort (status, "Unlock mutex");

        /*
         * We have a work item. Process it, which may involve
         * queuing new work items.
         */
        status = lstat (work->path, &filestat);

        if (S_ISLNK (filestat.st_mode))
            printf (
                "Thread %d: %s is a link, skipping.\n",
                mine->index,
                work->path);
        else if (S_ISDIR (filestat.st_mode)) {
            DIR *directory;
            struct dirent *result;

            /*
             * If the file is a directory, search it and place
             * all files onto the queue as new work items.
             */
            directory = opendir (work->path);
            if (directory == NULL) {
                fprintf (
                    stderr, "Unable to open directory %s: %d (%s)\n",
                    work->path,
                    errno, strerror (errno));
                continue;
            }
            
            while (1) {
                status = readdir_r (directory, entry, &result);
                if (status != 0) {
                    fprintf (
                        stderr,
                        "Unable to read directory %s: %d (%s)\n",
                        work->path,
                        status, strerror (status));
                    break;
                }
                if (result == NULL)
                    break;              /* End of directory */
                
                /*
                 * Ignore "." and ".." entries.
                 */
                if (strcmp (entry->d_name, ".") == 0)
                    continue;
                if (strcmp (entry->d_name, "..") == 0)
                    continue;
                new_work = (work_p)malloc (sizeof (work_t));
                if (new_work == NULL)
                    errno_abort ("Unable to allocate space");
                new_work->path = (char*)malloc (path_max);
                if (new_work->path == NULL)
                    errno_abort ("Unable to allocate path");
                strcpy (new_work->path, work->path);
                strcat (new_work->path, "/");
                strcat (new_work->path, entry->d_name);
                new_work->string = work->string;
                new_work->next = NULL;
                status = pthread_mutex_lock (&crew->mutex);
                if (status != 0)
                    err_abort (status, "Lock mutex");
                if (crew->first == NULL) {
                    crew->first = new_work;
                    crew->last = new_work;
                } else {
                    crew->last->next = new_work;
                    crew->last = new_work;
                }
                crew->work_count++;
                DPRINTF ((
                    "Crew %d: add work %#lx, first %#lx, last %#lx, %d\n",
                    mine->index, new_work, crew->first,
                    crew->last, crew->work_count));
                status = pthread_cond_signal (&crew->go);
                status = pthread_mutex_unlock (&crew->mutex);
                if (status != 0)
                    err_abort (status, "Unlock mutex");
            }
            
            closedir (directory);
        } else if (S_ISREG (filestat.st_mode)) {
            FILE *search;
            char buffer[256], *bufptr, *search_ptr;

            /*
             * If this is a file, not a directory, then search
             * it for the string.
             */
            search = fopen (work->path, "r");
            if (search == NULL)
                fprintf (
                    stderr, "Unable to open %s: %d (%s)\n",
                    work->path,
                    errno, strerror (errno));
            else {

                while (1) {
                    bufptr = fgets (
                        buffer, sizeof (buffer), search);
                    if (bufptr == NULL) {
                        if (feof (search))
                            break;
                        if (ferror (search)) {
                            fprintf (
                                stderr,
                                "Unable to read %s: %d (%s)\n",
                                work->path,
                                errno, strerror (errno));
                            break;
                        }
                    }
                    search_ptr = strstr (buffer, work->string);
                    if (search_ptr != NULL) {
                        flockfile (stdout);
                        printf (
                            "Thread %d found \"%s\" in %s\n",
                            mine->index, work->string, work->path);
#if 0
                        printf ("%s\n", buffer);
#endif
                        funlockfile (stdout);
                        break;
                    }
                }
                fclose (search);
            }
        } else
            fprintf (
                stderr,
                "Thread %d: %s is type %o (%s))\n",
                mine->index,
                work->path,
                filestat.st_mode & S_IFMT,
                (S_ISFIFO (filestat.st_mode) ? "FIFO"
                 : (S_ISCHR (filestat.st_mode) ? "CHR"
                    : (S_ISBLK (filestat.st_mode) ? "BLK"
                       : (S_ISSOCK (filestat.st_mode) ? "SOCK"
                          : "unknown")))));

        free (work->path);              /* Free path buffer */
        free (work);                    /* We're done with this */

        /*
         * Decrement count of outstanding work items, and wake
         * waiters (trying to collect results or start a new
         * calculation) if the crew is now idle.
         *
         * It's important that the count be decremented AFTER
         * processing the current work item. That ensures the
         * count won't go to 0 until we're really done.
         */
        status = pthread_mutex_lock (&crew->mutex);
        if (status != 0)
            err_abort (status, "Lock crew mutex");

        crew->work_count--;
        DPRINTF (("Crew %d decremented work to %d\n", mine->index,
                  crew->work_count));
        if (crew->work_count <= 0) {
            DPRINTF (("Crew thread %d done\n", mine->index));
            status = pthread_cond_broadcast (&crew->done);
            if (status != 0)
                err_abort (status, "Wake waiters");
            status = pthread_mutex_unlock (&crew->mutex);
            if (status != 0)
                err_abort (status, "Unlock mutex");
            break;
        }

        status = pthread_mutex_unlock (&crew->mutex);
        if (status != 0)
            err_abort (status, "Unlock mutex");

    }

    free (entry);
    return NULL;
}
コード例 #10
0
ファイル: crew.c プロジェクト: 1023xp/training
/*
 * Pass a file path to a work crew previously created
 * using crew_create
 */
int crew_start (
    crew_p crew,
    char *filepath,
    char *search)
{
    work_p request;
    int status;

    status = pthread_mutex_lock (&crew->mutex);
    if (status != 0)
        return status;

    /*
     * If the crew is busy, wait for them to finish.
     */
    while (crew->work_count > 0) {
        status = pthread_cond_wait (&crew->done, &crew->mutex);
        if (status != 0) {
            pthread_mutex_unlock (&crew->mutex);
            return status;
        }
    }

    errno = 0;
    path_max = pathconf (filepath, _PC_PATH_MAX);
    if (path_max == -1) {
        if (errno == 0)
            path_max = 1024;             /* "No limit" */
        else
            errno_abort ("Unable to get PATH_MAX");
    }
    errno = 0;
    name_max = pathconf (filepath, _PC_NAME_MAX);
    if (name_max == -1) {
        if (errno == 0)
            name_max = 256;             /* "No limit" */
        else
            errno_abort ("Unable to get NAME_MAX");
    }
    DPRINTF ((
        "PATH_MAX for %s is %ld, NAME_MAX is %ld\n",
        filepath, path_max, name_max));
    path_max++;                         /* Add null byte */
    name_max++;                         /* Add null byte */
    request = (work_p)malloc (sizeof (work_t));
    if (request == NULL)
        errno_abort ("Unable to allocate request");
    DPRINTF (("Requesting %s\n", filepath));
    request->path = (char*)malloc (path_max);
    if (request->path == NULL)
        errno_abort ("Unable to allocate path");
    strcpy (request->path, filepath);
    request->string = search;
    request->next = NULL;
    if (crew->first == NULL) {
        crew->first = request;
        crew->last = request;
    } else {
        crew->last->next = request;
        crew->last = request;
    }

    crew->work_count++;
    status = pthread_cond_signal (&crew->go);
    if (status != 0) {
        free (crew->first);
        crew->first = NULL;
        crew->work_count = 0;
        pthread_mutex_unlock (&crew->mutex);
        return status;
    }
    while (crew->work_count > 0) {
        status = pthread_cond_wait (&crew->done, &crew->mutex);
        if (status != 0)
            err_abort (status, "waiting for crew to finish");
    }
    status = pthread_mutex_unlock (&crew->mutex);
    if (status != 0)
        err_abort (status, "Unlock crew mutex");
    return 0;
}
コード例 #11
0
ファイル: multiPCav.c プロジェクト: oneminot/wsp
void *Consume (void *arg)
/* Consumer thread function. */
{
	msg_block_t *pmb;
	statistics_t * ps;
	int my_number, tstatus;
	struct timespec timeout, delta;
	
	delta.tv_sec = 2;
	delta.tv_nsec = 0;
		
	/* Create thread-specific storage key */
	tstatus = pthread_once (&once_control, once_init_function);
	if (tstatus != 0) err_abort (tstatus, "One time init failed");

	pmb = (msg_block_t *)arg;

	/* Allocate storage for thread-specific statistics */
	ps = calloc (sizeof(statistics_t), 1);
	if (ps == NULL) errno_abort ("Cannot allocate memory");
	tstatus = pthread_setspecific (ts_key, ps);
	if (tstatus != 0) err_abort (tstatus, "Error setting ts storage");
	ps->pmblock = pmb;
	/* Give this thread a unique number */
	/* Note that the mutex is "overloaded" to protect data	*/
	/* outside the message block structure			*/
	tstatus = pthread_mutex_lock (&pmb->nGuard);
	if (tstatus != 0) err_abort (tstatus, "Lock error");
	ps->th_number = thread_number++;
	tstatus = pthread_mutex_unlock (&pmb->nGuard);
	if (tstatus != 0) err_abort (tstatus, "Unlock error");
	
	/* Consume the NEXT message when prompted by the user */
	while (!pmb->fStop) { /* This is the only thread accessing stdin, stdout */
		tstatus = pthread_mutex_lock (&pmb->nGuard);
		if (tstatus != 0) err_abort (tstatus, "Lock error");
		/* Get the next message. Use a timed wait so as to be able	*/
		/* to sample the stop flag peridically.				*/
		do { 
			pthread_get_expiration_np (&delta, &timeout);
			tstatus = pthread_cond_timedwait 
				(&pmb->mReady, &pmb->nGuard, &timeout);
			if (tstatus != 0 && tstatus != ETIMEDOUT) 
				err_abort (tstatus, "CV wait error");
		} while (!pmb->f_ready && !pmb->fStop);
		if (!pmb->fStop) {
/*			printf ("Message received\n"); */
			accumulate_statistics ();
			pmb->f_consumed = 1;
			pmb->f_ready = 0;
		}
		tstatus = pthread_cond_signal (&pmb->mconsumed);
		if (tstatus != 0) err_abort (tstatus, "Signal error");
		tstatus = pthread_mutex_unlock (&pmb->nGuard);
		if (tstatus != 0) err_abort (tstatus, "Unlock error");
	}
	
	/* Shutdown. Report the statistics */
	tstatus = pthread_mutex_lock (&pmb->nGuard);
	if (tstatus != 0) err_abort (tstatus, "Lock error");
	report_statistics ();	
	tstatus = pthread_mutex_unlock (&pmb->nGuard);
	if (tstatus != 0) err_abort (tstatus, "Unlock error");

	/* Terminate the consumer thread. The destructor will 	*/
	/* free the memory allocated for the statistics		*/
	return NULL;		
}
コード例 #12
0
ファイル: server.c プロジェクト: cinderelladlw/pthread
void tty_server_request(int operation, int sync, const char *prompt, char *string)
{
	int status;
	request_t *request;

	status = pthread_mutex_lock(&server.mutex);
	if (status != 0) {
		err_abort(status, "Lock server mutex");
	}

	// check if server thread is already running
	if (!server.running) {
		pthread_t thread;
		pthread_attr_t detached_att;

		status = pthread_attr_init(&detached_att);
		if (status != 0) {
			err_abort(status, "Init detached attribute");
		}

		// set detached attribute for server thread
		status = pthread_attr_setdetachstate(&detached_att, PTHREAD_CREATE_DETACHED);
		if (status != 0) {
			err_abort(status, "Set detach state");
		}

		status = pthread_create(&thread, &detached_att, server_routine, NULL);
		if (status != 0) {
			err_abort(status, "Create server routine");
		}
		server.running = 1;

		status = pthread_attr_destroy(&detached_att);
		if (status != 0) {
			fprintf(stderr, "Destroy detached attribute");
		}
	}

	// add request
	request = malloc(sizeof(request_t));
	if (request == NULL) {
		errno_abort("Allocate memory for request");
	}

	request->next = NULL;
	request->operation = operation;
	request->synchronous = sync;

	// only init condition variable for sync request
	if (sync) {
		request->done_flag = 0;
		pthread_cond_init(&request->done, NULL);
	}

	if (prompt != NULL) {
		strncpy(request->prompt, prompt, PROMPT_MAX);
	}
	else {
		request->prompt[0] = '\0';
	}

	if (operation == REQ_WRITE && string != NULL) {
		strncpy(request->text, string, TEXT_MAX);
	}
	else {
		request->text[0] = '\0';
	}

	if (server.first == NULL) {
		server.first = server.last = request;
	}
	else {
		server.last->next = request;
		server.last = request;
	}

	pthread_cond_signal(&server.request);

	// destory condition variable for sync request
	if (sync) {
		while (!request->done_flag) {
			status = pthread_cond_wait(&request->done, &server.mutex);
			if (status != 0) {
				err_abort(status, "Wait on request done cond");
			}
		}

		if (operation == REQ_READ) {
			if (strlen(request->text) > 0) {
				strncpy(string, request->text, TEXT_MAX);
			}
		}

		status = pthread_cond_destroy(&request->done);
		if (status != 0) {
			err_abort(status, "Destroy request done cond");
		}
		free(request);
	}

	status = pthread_mutex_unlock(&server.mutex);
	if (status != 0) {
		err_abort(status, "Unlock server mutex");
	}
}
コード例 #13
0
ファイル: server.c プロジェクト: abo321/PosixThreads
/*
 * Request an operation
 */
void tty_server_request (
    int         operation,
    int         sync,
    const char  *prompt,
    char        *string)
{
    request_t *request;
    int status;

    status = pthread_mutex_lock (&tty_server.mutex);
    if (status != 0)
        err_abort (status, "Lock server mutex");
    if (!tty_server.running) {
        pthread_t thread;
        pthread_attr_t detached_attr;

        status = pthread_attr_init (&detached_attr);
        if (status != 0)
            err_abort (status, "Init attributes object");
        status = pthread_attr_setdetachstate (
            &detached_attr, PTHREAD_CREATE_DETACHED);
        if (status != 0)
            err_abort (status, "Set detach state");
        tty_server.running = 1;
        status = pthread_create (&thread, &detached_attr,
            tty_server_routine, NULL);
        if (status != 0)
            err_abort (status, "Create server");

        /*
         * Ignore an error in destroying the attributes object.
         * It's unlikely to fail, there's nothing useful we can
         * do about it, and it's not worth aborting the program
         * over it.
         */
        pthread_attr_destroy (&detached_attr);
    }

    /*
     * Create and initialize a request structure.
     */
    request = (request_t*)malloc (sizeof (request_t));
    if (request == NULL)
        errno_abort ("Allocate request");
    request->next = NULL;
    request->operation = operation;
    request->synchronous = sync;
    if (sync) {
        request->done_flag = 0;
        status = pthread_cond_init (&request->done, NULL);
        if (status != 0)
            err_abort (status, "Init request condition");
    }
    if (prompt != NULL)
        strncpy (request->prompt, prompt, 32);
    else
        request->prompt[0] = '\0';
    if (operation == REQ_WRITE && string != NULL)
        strncpy (request->text, string, 128);
    else
        request->text[0] = '\0';

    /*
     * Add the request to the queue, maintaining the first and
     * last pointers.
     */
    if (tty_server.first == NULL) {
        tty_server.first = request;
        tty_server.last = request;
    } else {
        (tty_server.last)->next = request;
        tty_server.last = request;
    }

    /*
     * Tell the server that a request is available.
     */
    status = pthread_cond_signal (&tty_server.request);
    if (status != 0)
        err_abort (status, "Wake server");

    /*
     * If the request was "synchronous", then wait for a reply.
     */
    if (sync) {
        while (!request->done_flag) {
            status = pthread_cond_wait (
                &request->done, &tty_server.mutex);
            if (status != 0)
                err_abort (status, "Wait for sync request");
        }
        if (operation == REQ_READ) {
            if (strlen (request->text) > 0)
                strcpy (string, request->text);
            else
                string[0] = '\0';
        }
        status = pthread_cond_destroy (&request->done);
        if (status != 0)
            err_abort (status, "Destroy request condition");
        free (request);
    }
    status = pthread_mutex_unlock (&tty_server.mutex);
    if (status != 0)
        err_abort (status, "Unlock mutex");
}