Ejemplo n.º 1
0
DEVTHREADPARMS*  CreateDeviceThread(unsigned short wDevNum)
{
    DEVTHREADPARMS*  pThreadParms;      // ptr to returned device_thread parameters
    DWORD            dwThreadID;        // (work)

    pThreadParms = malloc(sizeof(DEVTHREADPARMS));      // (allocate structure)

    if (!pThreadParms)
    {
        WRMSG ( HHC04111, "E", 0, wDevNum, "malloc(DEVTHREADPARMS)", errno, strerror(errno) );
        return NULL;    // (error)
    }

    pThreadParms->hShutdownEvent = MyCreateEvent(NULL,TRUE,FALSE,NULL);

    if (!pThreadParms->hShutdownEvent)
    {
        WRMSG ( HHC04111, "E", 0, wDevNum, "CreateEvent(hShutdownEvent)", errno, strerror(errno) );
        free(pThreadParms);
        return NULL;    // (error)
    }

    pThreadParms->hRequestQueuedEvent = MyCreateEvent(NULL,TRUE,FALSE,NULL);

    if (!pThreadParms->hRequestQueuedEvent)
    {
        WRMSG ( HHC04111, "E", 0, wDevNum, "CreateEvent(hRequestQueuedEvent)", errno, strerror(errno) );
        MyCloseHandle(pThreadParms->hShutdownEvent);
        free(pThreadParms);
        return NULL;    // (error)
    }

    MyInitializeCriticalSection(&pThreadParms->IORequestListLock);

    InitializeListLink(&pThreadParms->ThreadListLinkingListEntry);
    InitializeListHead(&pThreadParms->IORequestListHeadListEntry);

    pThreadParms->bThreadIsDead = FALSE;
    pThreadParms->dwThreadID = 0;

    if (fthread_create(&dwThreadID,NULL,DeviceThread,pThreadParms,"DeviceThread") != 0)
    {
        WRMSG ( HHC04111, "E", 0, wDevNum, "fthread_create(DeviceThread)", errno, strerror(errno) );
        MyCloseHandle(pThreadParms->hShutdownEvent);
        MyCloseHandle(pThreadParms->hRequestQueuedEvent);
        MyDeleteCriticalSection(&pThreadParms->IORequestListLock);
        free(pThreadParms);
        return NULL;    // (error)
    }

    // Add the newly created device_thread to the end of our list of managed threads.

    InsertListTail(&ThreadListHeadListEntry,&pThreadParms->ThreadListLinkingListEntry);

    if (++ios_devtnbr > ios_devthwm) ios_devthwm = ios_devtnbr;

    LockThreadParms(pThreadParms);  // (lock thread parms before using)

    return pThreadParms;            // (success)
}
Ejemplo n.º 2
0
DLL_EXPORT
void FishHangInit( const char* pszFileCreated, const int nLineCreated )
{
    FISH_THREAD*  pFISH_THREAD;

    FIXFILENAME(pszFileCreated);

    if ( !( fh_report_stream = fopen( "FishHangReport.txt", "w" ) ) )
    {
        perror( "FishHang report o/p file open failure" );
        abort();
    }

    InitializeListHead(&ThreadsListHead);
    InitializeListHead(&LocksListHead);
    InitializeListHead(&EventsListHead);
    InitializeCriticalSection(&ListsLock);

    if (!(pFISH_THREAD = CreateFISH_THREAD(pszFileCreated,nLineCreated)))
    {
        logmsg("** FishHangInit: CreateFISH_THREAD failed\n");
        exit(-1);
    }

    pFISH_THREAD->dwThreadID = GetCurrentThreadId();
    InsertListTail(&ThreadsListHead,&pFISH_THREAD->ThreadListLink);
}
Ejemplo n.º 3
0
DEVTHREADPARMS*  SelectDeviceThread()
{
    DEVTHREADPARMS*  pThreadParms;      // ptr to selected device thread
    LIST_ENTRY*      pListEntry;        // (work)

    pListEntry = ThreadListHeadListEntry.Flink;

    while (pListEntry != &ThreadListHeadListEntry)
    {
        pThreadParms = CONTAINING_RECORD(pListEntry,DEVTHREADPARMS,ThreadListLinkingListEntry);

        LockThreadParms(pThreadParms);      // (freeze moving target)

        if (pThreadParms->bThreadIsDead)
        {
            UnlockThreadParms(pThreadParms);
            RemoveThisThreadFromOurList(pThreadParms);
            pListEntry = ThreadListHeadListEntry.Flink;
            continue;
        }

        if (!IsEventSet(pThreadParms->hRequestQueuedEvent))
        {
            RemoveListEntry(pListEntry);
            InsertListTail(&ThreadListHeadListEntry,pListEntry);
            return pThreadParms;
        }

        UnlockThreadParms(pThreadParms);    // (can't use this one)

        pListEntry = pListEntry->Flink;
    }

    return NULL;    // (all of them are busy)
}
Ejemplo n.º 4
0
DLL_EXPORT
BOOL FishHang_TryEnterCriticalSection
(
    const char*  pszFileWaiting,  // source file that attempted it
    const int    nLineWaiting,    // line number of source file

    LPCRITICAL_SECTION lpCriticalSection   // address of critical section object
)
{
    FISH_THREAD*  pFISH_THREAD;
    FISH_LOCK*    pFISH_LOCK;
    BOOL          bSuccess;

    FIXFILENAME(pszFileWaiting);

    LockFishHang();

    if (!GetThreadAndLockPtrs(&pFISH_THREAD,&pFISH_LOCK,lpCriticalSection))
        FishHangAbort(pszFileWaiting,nLineWaiting);

    pFISH_THREAD->bWaitingForLock = FALSE;
    pFISH_THREAD->bTryingForLock  = TRUE;
    pFISH_THREAD->pWhatWaiting    = pFISH_LOCK;
    pFISH_THREAD->pszFileWaiting  = pszFileWaiting;
    pFISH_THREAD->nLineWaiting    = nLineWaiting;

    GetSystemTime(&pFISH_THREAD->timeWaiting);

    if (PrintDeadlock(pFISH_THREAD,pszFileWaiting,nLineWaiting))
        FishHangAbort(pszFileWaiting,nLineWaiting);

    UnlockFishHang();

    bSuccess = TryEnterCriticalSection(lpCriticalSection);

    LockFishHang();

    pFISH_THREAD->bTryingForLock = FALSE;

    if (bSuccess)
    {
        pFISH_THREAD->bWaitingForLock = FALSE;

        if (pFISH_LOCK->pOwningThread != pFISH_THREAD)
        {
            pFISH_LOCK->pOwningThread = pFISH_THREAD;
            pFISH_LOCK->nLockedDepth = 1;
            InsertListTail(&pFISH_THREAD->ThreadLockListHead,&pFISH_LOCK->ThreadLockListLink);
        }
        else
        {
            pFISH_LOCK->nLockedDepth++;
        }
    }

    UnlockFishHang();

    return bSuccess;
}
Ejemplo n.º 5
0
DLL_EXPORT
HANDLE FishHang_CreateThread
(
    const char*  pszFileCreated,  // source file that created it
    const int    nLineCreated,    // line number of source file

    LPSECURITY_ATTRIBUTES   lpThreadAttributes, // pointer to security attributes
    DWORD                   dwStackSize,        // initial thread stack size
    LPTHREAD_START_ROUTINE  lpStartAddress,     // pointer to thread function
    LPVOID                  lpParameter,        // argument for new thread
    DWORD                   dwCreationFlags,    // creation flags
    LPDWORD                 lpThreadId          // pointer to receive thread ID
)
{
    FISH_THREAD*  pFISH_THREAD;
    HANDLE        hThread;

    FIXFILENAME(pszFileCreated);

    if (!(pFISH_THREAD = CreateFISH_THREAD(pszFileCreated,nLineCreated))) return NULL;

#ifdef _MSVC_
    hThread = (HANDLE) _beginthreadex
#else // (Cygwin)
    hThread = CreateThread
#endif
    (
        lpThreadAttributes, // pointer to security attributes
        dwStackSize,        // initial thread stack size
        lpStartAddress,     // pointer to thread function
        lpParameter,        // argument for new thread
        dwCreationFlags,    // creation flags
        lpThreadId          // pointer to receive thread ID
    );

    if (hThread)
    {
        pFISH_THREAD->dwThreadID = *lpThreadId;

        LockFishHang();
        InsertListTail(&ThreadsListHead,&pFISH_THREAD->ThreadListLink);
        UnlockFishHang();
    }
    else
    {
        free(pFISH_THREAD);
    }

    return hThread;
}
Ejemplo n.º 6
0
/*-------------------------------------------------------------------*/
static ILOCK* hthreads_get_ILOCK( void* addr, const char* name )
{
    ILOCK*       ilk;               /* Pointer to ILOCK structure    */
    LIST_ENTRY*  ple;               /* Ptr to LIST_ENTRY structure   */

    hthreads_internal_init();

    /* Search list to see if this lock has already been allocated */

    LockLocksList();

    for (ple = locklist.Flink; ple != &locklist; ple = ple->Flink)
    {
        ilk = CONTAINING_RECORD( ple, ILOCK, locklink );
        if (ilk->addr == addr)
            break;
    }

    /* If needed, alloacte a new ILOCK structure for this lock */

    if (&locklist == ple)
    {
        if (!(ilk = calloc_aligned( sizeof( ILOCK ), 64 )))
        {
            perror( "Fatal error in hthreads_get_ILOCK function" );
            exit(1);
        }
        ilk->addr = addr;
        InsertListTail( &locklist, &ilk->locklink );
        lockcount++;
    }

    ilk->name = name;
    ilk->location = "null:0";
    ilk->tid = 0;
    ilk->time.tv_sec = 0;
    ilk->time.tv_usec = 0;

    UnlockLocksList();

    return ilk;
}
Ejemplo n.º 7
0
DLL_EXPORT
void FishHang_InitializeCriticalSection
(
    const char*  pszFileCreated,  // source file that created it
    const int    nLineCreated,    // line number of source file

    LPCRITICAL_SECTION lpCriticalSection   // address of critical section object
)
{
    FISH_LOCK*  pFISH_LOCK;

    FIXFILENAME(pszFileCreated);

    LockFishHang();

    pFISH_LOCK = FindFISH_LOCK(lpCriticalSection);

    if (pFISH_LOCK)
    {
        logmsg(
            "** ERROR ** FISH_LOCK %8.8X already initialized!\n",
            (int)pFISH_LOCK);
        logmsg("%s(%d)\n",pszFileCreated,nLineCreated);
        logmsg("%s\n",PrintFISH_LOCK(pFISH_LOCK));
        FishHangAbort(pszFileCreated,nLineCreated);
    }

    if (!(pFISH_LOCK = CreateFISH_LOCK(pszFileCreated,nLineCreated)))
    {
        logmsg("** FishHang_InitializeCriticalSection: CreateFISH_LOCK failed!\n");
        FishHangAbort(pszFileCreated,nLineCreated);
    }

    InitializeCriticalSection(lpCriticalSection);
    pFISH_LOCK->pLock = lpCriticalSection;
    InsertListTail(&LocksListHead,&pFISH_LOCK->LockListLink);

    UnlockFishHang();
}
Ejemplo n.º 8
0
DLL_EXPORT
HANDLE FishHang_CreateEvent
(
    const char*  pszFileCreated,  // source file that created it
    const int    nLineCreated,    // line number of source file

    LPSECURITY_ATTRIBUTES  lpEventAttributes,   // pointer to security attributes
    BOOL                   bManualReset,        // flag for manual-reset event
    BOOL                   bInitialState,       // flag for initial state
    LPCTSTR                lpName               // pointer to event-object name
)
{
    FISH_EVENT*  pFISH_EVENT;
    HANDLE       hEvent;

    FIXFILENAME(pszFileCreated);

    if (!(pFISH_EVENT = CreateFISH_EVENT(pszFileCreated,nLineCreated)))
    {
        logmsg("** FishHang_CreateEvent: CreateFISH_EVENT failed\n");
        exit(-1);
    }

    if (!(hEvent = CreateEvent(lpEventAttributes,bManualReset,bInitialState,lpName)))
    {
        free(pFISH_EVENT);
    }
    else
    {
        pFISH_EVENT->hEvent = hEvent;

        LockFishHang();
        InsertListTail(&EventsListHead,&pFISH_EVENT->EventsListLink);
        UnlockFishHang();
    }

    return hEvent;
}
Ejemplo n.º 9
0
int  ScheduleIORequest(void* pDevBlk, unsigned short wDevNum, int* pnDevPrio)
{
    /////////////////////////////////////////////////////////////////
    // PROGRAMMING NOTE: The various errors that can occur in this
    // function should probably be reported by returning cc1 with
    // 'channel control check' set (or something similar), but until
    // I can work out the details, I'm going to be lazy and just
    // return cc2 (subchannel busy) for now to allow the system to
    // retry the i/o request if it so desires. Hopefully the problem
    // was only intermittent and will work the second time around.
    /////////////////////////////////////////////////////////////////

    DEVIOREQUEST*    pIORequest;            // ptr to i/o request
    DEVTHREADPARMS*  pThreadParms;          // ptr to device_thread parameters

    // Create an i/o request queue entry for this i/o request

    pIORequest = (DEVIOREQUEST*) malloc(sizeof(DEVIOREQUEST));

    if (!pIORequest)
    {
        WRMSG ( HHC04111, "E", 0, wDevNum, "malloc(DEVIOREQUEST)", errno, strerror(errno) );
        return 2;
    }

    InitializeListLink(&pIORequest->IORequestListLinkingListEntry);
    pIORequest->pDevBlk = pDevBlk;
    pIORequest->wDevNum = wDevNum;
    pIORequest->pnDevPrio = pnDevPrio;

    // Schedule a device_thread to process this i/o request

    LockScheduler();        // (lock scheduler vars)

    if (ios_devtmax < 0)
    {
        // Create new "one time only" thread each time...

        // (Note: the device thread's parms will automatically
        //  be locked upon return if creation was successful.)

        RemoveDeadThreadsFromList();    // (prevent runaway list)

        if (!(pThreadParms = CreateDeviceThread(wDevNum)))
        {
            UnlockScheduler();          // (unlock scheduler vars)
            free(pIORequest);           // (discard i/o request)
            return 2;                   // (return device busy)
        }
    }
    else
    {
        // Select a non-busy device thread to handle this i/o request...

        // (Note: the device thread's parms will automatically
        //  be locked upon return if selection was successful.)

        if (!(pThreadParms = SelectDeviceThread()))
        {
            // All threads are currently busy or no threads exist yet.

            // Since the possibility of a deadlock[1] can easily occur if we schedule
            // an i/o request to a currently busy device thread[2], we have no choice
            // but to create another device thread.

            // [1] Not an actual programmatic deadlock of course, but nonetheless
            //     a deadlock from the guest operating system's point of view.

            // [2] A curently busy device thread could easily have its channel program
            //     suspended and thus would never see the queued request until such time
            //     its suspended channel program was resumed and allowed to complete, and
            //     if the request we queued (that would end up waiting to be processed
            //     by the currently suspended device thread) just so happens to be one
            //     that the operating system needs to have completed before it can resume
            //     the currently suspended channel program, then the operating system will
            //     obviously hang. (It would end up waiting for an i/o to complete that
            //     would never complete until the currently suspended channel program was
            //     resumed, which would never be resumed until the queued i/o completes,
            //     which would never even be processed until the currently suspended
            //     channel program is resumed ..... etc.)

            if (ios_devtmax && ios_devtnbr >= ios_devtmax)  // max threads already created?
            {
                WRMSG ( HHC04110, "W", ios_devtmax, ( ios_devtnbr - ios_devtmax ) + 1 );
                ios_devtunavail++;          // (count occurrences)
            }

            // Create a new device thread for this i/o request...

            // (Note: the device thread's parms will automatically
            //  be locked upon return if creation was successful.)

            if (!(pThreadParms = CreateDeviceThread(wDevNum)))
            {
                UnlockScheduler();          // (unlock scheduler vars)
                free(pIORequest);           // (discard i/o request)
                return 2;                   // (return device busy)
            }
        }
    }

    // (Note: the thread parms lock should still be held at this point)

    // Queue the i/o request to the selected device_thread's i/o request queue...

    InsertListTail(&pThreadParms->IORequestListHeadListEntry,&pIORequest->IORequestListLinkingListEntry);

    // Tell device_thread it has work (must do this while its request list is still
    // locked to prevent it from prematurely exiting in case it's just about to die)

    MySetEvent(pThreadParms->hRequestQueuedEvent);

    // Now unlock its request queue so it can process the request we just gave it

    UnlockThreadParms(pThreadParms);        // (let it proceed)

    // We're done, so unlock the scheduler vars so another cpu thread
    // in the configuration can schedule and i/o request and then exit
    // back the the startio function...

    UnlockScheduler();          // (unlock vars and exit; we're done)

    return 0;                   // (success)
}
Ejemplo n.º 10
0
/*-------------------------------------------------------------------*/
int bind_device_ex (DEVBLK* dev, char* spec, ONCONNECT fn, void* arg )
{
    bind_struct* bs;
    int was_list_empty;

    if (!init_done) init_sockdev();

    if (sysblk.shutdown) return 0;

    logdebug("bind_device (%4.4X, %s)\n", dev->devnum, spec);

    /* Error if device already bound */
    if (dev->bs)
    {
        logmsg (_("HHCSD001E Device %4.4X already bound to socket %s\n"),
            dev->devnum, dev->bs->spec);
        return 0;   /* (failure) */
    }

    /* Create a new bind_struct entry */
    bs = malloc(sizeof(bind_struct));

    if (!bs)
    {
        logmsg (_("HHCSD002E bind_device malloc() failed for device %4.4X\n"),
            dev->devnum);
        return 0;   /* (failure) */
    }

    memset(bs,0,sizeof(bind_struct));

    bs->fn  = fn;
    bs->arg = arg;

    if (!(bs->spec = strdup(spec)))
    {
        logmsg (_("HHCSD003E bind_device strdup() failed for device %4.4X\n"),
            dev->devnum);
        free (bs);
        return 0;   /* (failure) */
    }

    /* Create a listening socket */
    if (bs->spec[0] == '/') bs->sd = unix_socket (bs->spec);
    else                    bs->sd = inet_socket (bs->spec);
    if (bs->sd == -1)
    {
        /* (error message already issued) */
        free( bs->spec );
        free( bs );
        return 0; /* (failure) */
    }

    /* Chain device and bind_struct to each other */
    dev->bs = bs;
    bs->dev = dev;

    /* Add the new entry to our list of bound devices
       and create the socket thread that will listen
       for connections (if it doesn't already exist) */

    obtain_lock( &bind_lock );

    was_list_empty = IsListEmpty( &bind_head );

    InsertListTail( &bind_head, &bs->bind_link );

    if ( was_list_empty )
    {
        if ( create_thread( &sysblk.socktid, JOINABLE,
                            socket_thread, NULL, "socket_thread" ) )
            {
                logmsg( _( "HHCSD023E Cannot create socketdevice thread: errno=%d: %s\n" ),
                        errno, strerror( errno ) );
                RemoveListEntry( &bs->bind_link );
                close_socket(bs->sd);
                free( bs->spec );
                free( bs );
                release_lock( &bind_lock );
                return 0; /* (failure) */
            }
    }

    SIGNAL_SOCKDEV_THREAD();

    release_lock( &bind_lock );

    logmsg (_("HHCSD004I Device %4.4X bound to socket %s\n"),
        dev->devnum, dev->bs->spec);

    return 1;   /* (success) */
}
Ejemplo n.º 11
0
/*-------------------------------------------------------------------*/
int bind_device_ex (DEVBLK* dev, char* spec, ONCONNECT fn, void* arg )
{
    bind_struct* bs;
    int was_list_empty;
    int rc;

    if (!init_done) init_sockdev();

    if (sysblk.shutdown) return 0;

    logdebug("bind_device (%4.4X, %s)\n", dev->devnum, spec);

    /* Error if device already bound */
    if (dev->bs)
    {
        WRMSG (HHC01041, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->bs->spec);
        return 0;   /* (failure) */
    }

    /* Create a new bind_struct entry */
    bs = malloc(sizeof(bind_struct));

    if (!bs)
    {
        char buf[40];
        MSGBUF( buf, "malloc(%d)", (int)sizeof(bind_struct));
        WRMSG (HHC01000, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, buf, strerror(errno));
        return 0;   /* (failure) */
    }

    memset(bs, 0, sizeof(bind_struct));

    bs->fn  = fn;
    bs->arg = arg;

    if (!(bs->spec = strdup(spec)))
    {
        WRMSG (HHC01000, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, "strdup()", strerror(errno) );
        free (bs);
        return 0;   /* (failure) */
    }

    /* Create a listening socket */
    if (bs->spec[0] == '/') bs->sd = unix_socket (bs->spec);
    else                    bs->sd = inet_socket (bs->spec);
    if (bs->sd == -1)
    {
        /* (error message already issued) */
        free( bs->spec );
        free( bs );
        return 0; /* (failure) */
    }

    /* Chain device and bind_struct to each other */
    dev->bs = bs;
    bs->dev = dev;

    /* Add the new entry to our list of bound devices
       and create the socket thread that will listen
       for connections (if it doesn't already exist) */

    obtain_lock( &bind_lock );

    was_list_empty = IsListEmpty( &bind_head );

    InsertListTail( &bind_head, &bs->bind_link );

    if ( was_list_empty )
    {
        rc = create_thread( &sysblk.socktid, JOINABLE,
                            socket_thread, NULL, "socket_thread" );
        if (rc)
        {
            WRMSG(HHC00102, "E", strerror( rc ) );
            RemoveListEntry( &bs->bind_link );
            close_socket(bs->sd);
            free( bs->spec );
            free( bs );
            release_lock( &bind_lock );
            return 0; /* (failure) */
        }
    }

    SIGNAL_SOCKDEV_THREAD();

    release_lock( &bind_lock );

    WRMSG (HHC01042, "I", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->bs->spec);

    return 1;   /* (success) */
}