michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: * File: primblok.c michael@0: * Purpose: testing whether the primordial thread can block in a michael@0: * native blocking function without affecting the correct michael@0: * functioning of NSPR I/O functions (Bugzilla bug #30746) michael@0: */ michael@0: michael@0: #if !defined(WINNT) michael@0: michael@0: #include michael@0: michael@0: int main(int argc, char **argv) michael@0: { michael@0: printf("This test is not relevant on this platform\n"); michael@0: return 0; michael@0: } michael@0: michael@0: #else /* WINNT */ michael@0: michael@0: #include "nspr.h" michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #define TEST_FILE_NAME "primblok.dat" michael@0: michael@0: /* use InterlockedExchange to update this variable */ michael@0: static LONG iothread_done; michael@0: michael@0: static void PR_CALLBACK IOThread(void *arg) michael@0: { michael@0: PRFileDesc *fd; michael@0: char buf[32]; michael@0: PRInt32 nbytes; michael@0: michael@0: /* Give the primordial thread one second to block */ michael@0: Sleep(1000); michael@0: michael@0: /* michael@0: * See if our PR_Write call will hang when the primordial michael@0: * thread is blocking in a native blocking function. michael@0: */ michael@0: fd = PR_Open(TEST_FILE_NAME, PR_WRONLY|PR_CREATE_FILE, 0666); michael@0: if (NULL == fd) { michael@0: fprintf(stderr, "PR_Open failed\n"); michael@0: exit(1); michael@0: } michael@0: memset(buf, 0xaf, sizeof(buf)); michael@0: fprintf(stderr, "iothread: calling PR_Write\n"); michael@0: nbytes = PR_Write(fd, buf, sizeof(buf)); michael@0: fprintf(stderr, "iothread: PR_Write returned\n"); michael@0: if (nbytes != sizeof(buf)) { michael@0: fprintf(stderr, "PR_Write returned %d\n", nbytes); michael@0: exit(1); michael@0: } michael@0: if (PR_Close(fd) == PR_FAILURE) { michael@0: fprintf(stderr, "PR_Close failed\n"); michael@0: exit(1); michael@0: } michael@0: if (PR_Delete(TEST_FILE_NAME) == PR_FAILURE) { michael@0: fprintf(stderr, "PR_Delete failed\n"); michael@0: exit(1); michael@0: } michael@0: michael@0: /* Tell the main thread that we are done */ michael@0: InterlockedExchange(&iothread_done, 1); michael@0: } michael@0: michael@0: int main(int argc, char **argv) michael@0: { michael@0: PRThread *iothread; michael@0: michael@0: /* Must be a global thread */ michael@0: iothread = PR_CreateThread( michael@0: PR_USER_THREAD, IOThread, NULL, PR_PRIORITY_NORMAL, michael@0: PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); michael@0: if (iothread == NULL) { michael@0: fprintf(stderr, "cannot create thread\n"); michael@0: exit(1); michael@0: } michael@0: michael@0: /* michael@0: * Block in a native blocking function. michael@0: * Give iothread 5 seconds to finish its task. michael@0: */ michael@0: Sleep(5000); michael@0: michael@0: /* michael@0: * Is iothread done or is it hung? michael@0: * michael@0: * I'm actually only interested in reading the value michael@0: * of iothread_done. I'm using InterlockedExchange as michael@0: * a thread-safe way to read iothread_done. michael@0: */ michael@0: if (InterlockedExchange(&iothread_done, 1) == 0) { michael@0: fprintf(stderr, "iothread is hung\n"); michael@0: fprintf(stderr, "FAILED\n"); michael@0: exit(1); michael@0: } michael@0: michael@0: if (PR_JoinThread(iothread) == PR_FAILURE) { michael@0: fprintf(stderr, "PR_JoinThread failed\n"); michael@0: exit(1); michael@0: } michael@0: printf("PASSED\n"); michael@0: return 0; michael@0: } /* main */ michael@0: michael@0: #endif /* WINNT */