nsprpub/pr/tests/ioconthr.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/nsprpub/pr/tests/ioconthr.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,114 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +/*
    1.10 + * This is a test for the io continuation thread machinery
    1.11 + * in pthreads.
    1.12 + */
    1.13 +
    1.14 +#include "nspr.h"
    1.15 +#include <stdio.h>
    1.16 +
    1.17 +int num_threads = 10;  /* must be an even number */
    1.18 +PRThreadScope thread_scope = PR_GLOBAL_THREAD;
    1.19 +
    1.20 +void ThreadFunc(void *arg)
    1.21 +{
    1.22 +    PRFileDesc *fd = (PRFileDesc *) arg;
    1.23 +    char buf[1024];
    1.24 +    PRInt32 nbytes;
    1.25 +    PRErrorCode err;
    1.26 +
    1.27 +    nbytes = PR_Recv(fd, buf, sizeof(buf), 0, PR_SecondsToInterval(20));
    1.28 +    if (nbytes == -1) {
    1.29 +        err = PR_GetError();
    1.30 +        if (err != PR_PENDING_INTERRUPT_ERROR) {
    1.31 +            fprintf(stderr, "PR_Recv failed: (%d, %d)\n",
    1.32 +                    err, PR_GetOSError());
    1.33 +            PR_ProcessExit(1);
    1.34 +        }
    1.35 +        /*
    1.36 +         * After getting an I/O interrupt, this thread must
    1.37 +         * close the fd before it exits due to a limitation
    1.38 +         * of our NT implementation.
    1.39 +         */
    1.40 +        if (PR_Close(fd) == PR_FAILURE) {
    1.41 +            fprintf(stderr, "PR_Close failed\n");
    1.42 +            PR_ProcessExit(1);
    1.43 +        }
    1.44 +    } else {
    1.45 +        fprintf(stderr, "PR_Recv received %d bytes!?\n", nbytes);
    1.46 +        PR_ProcessExit(1);
    1.47 +    }
    1.48 +}
    1.49 +
    1.50 +int main(int argc, char **argv)
    1.51 +{
    1.52 +    PRFileDesc **fds;
    1.53 +    PRThread **threads;
    1.54 +    PRIntervalTime start, elapsed;
    1.55 +    int index;
    1.56 +
    1.57 +    fds = (PRFileDesc **) PR_MALLOC(2 * num_threads * sizeof(PRFileDesc *));
    1.58 +    PR_ASSERT(fds != NULL);
    1.59 +    threads = (PRThread **) PR_MALLOC(num_threads * sizeof(PRThread *));
    1.60 +    PR_ASSERT(threads != NULL);
    1.61 +
    1.62 +    for (index = 0; index < num_threads; index++) {
    1.63 +        if (PR_NewTCPSocketPair(&fds[2 * index]) == PR_FAILURE) {
    1.64 +            fprintf(stderr, "PR_NewTCPSocket failed\n");
    1.65 +            PR_ProcessExit(1);
    1.66 +        }
    1.67 +        threads[index] = PR_CreateThread(
    1.68 +                PR_USER_THREAD, ThreadFunc, fds[2 * index],
    1.69 +                PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0);
    1.70 +        if (NULL == threads[index]) {
    1.71 +            fprintf(stderr, "PR_CreateThread failed\n");
    1.72 +            PR_ProcessExit(1);
    1.73 +        }
    1.74 +    }
    1.75 +
    1.76 +    /* Let the threads block in PR_Recv */
    1.77 +    PR_Sleep(PR_SecondsToInterval(2));
    1.78 +
    1.79 +    printf("Interrupting the threads\n");
    1.80 +    fflush(stdout);
    1.81 +    start = PR_IntervalNow();
    1.82 +    for (index = 0; index < num_threads; index++) {
    1.83 +        if (PR_Interrupt(threads[index]) == PR_FAILURE) {
    1.84 +            fprintf(stderr, "PR_Interrupt failed\n");
    1.85 +            PR_ProcessExit(1);
    1.86 +        }
    1.87 +    }
    1.88 +    for (index = 0; index < num_threads; index++) {
    1.89 +        if (PR_JoinThread(threads[index]) == PR_FAILURE) {
    1.90 +            fprintf(stderr, "PR_JoinThread failed\n");
    1.91 +            PR_ProcessExit(1);
    1.92 +        }
    1.93 +    }
    1.94 +    elapsed = (PRIntervalTime)(PR_IntervalNow() - start);
    1.95 +    printf("Threads terminated in %d milliseconds\n",
    1.96 +            PR_IntervalToMilliseconds(elapsed));
    1.97 +    fflush(stdout);
    1.98 +    
    1.99 +    /* We are being very generous and allow 10 seconds. */
   1.100 +    if (elapsed >= PR_SecondsToInterval(10)) {
   1.101 +        fprintf(stderr, "Interrupting threads took longer than 10 seconds!!\n");
   1.102 +        PR_ProcessExit(1);
   1.103 +    }
   1.104 +
   1.105 +    for (index = 0; index < num_threads; index++) {
   1.106 +        /* fds[2 * index] was passed to and closed by threads[index]. */
   1.107 +        if (PR_Close(fds[2 * index + 1]) == PR_FAILURE) {
   1.108 +            fprintf(stderr, "PR_Close failed\n");
   1.109 +            PR_ProcessExit(1);
   1.110 +        }
   1.111 +    }
   1.112 +    PR_DELETE(threads);
   1.113 +    PR_DELETE(fds);
   1.114 +    printf("PASS\n");
   1.115 +    PR_Cleanup();
   1.116 +    return 0;
   1.117 +}

mercurial