Пример #1
0
void ScanAsyncFile::clean_slots()
 {
  pbuf.detach();

  while( done_count )
    {
     slots[done_ind].pbuf.detach();

     done_ind=NextInd(done_ind);
     done_count--;
    }

  while( op_count )
    {
     slots[op_ind].pbuf.detach();

     op_ind=NextInd(op_ind);
     op_count--;
    }
 }
Пример #2
0
PtrLen<const char> ScanAsyncFile::underflow()
 {
  if( !is_opened )
    {
     fail();

     Printf(Exception,"CCore::ScanAsyncFile::underflow() : file is not opened");

     return Nothing;
    }

  if( !remaining_len ) return Nothing;

  TimeScope time_scope(timeout);

  pump_read(time_scope);

  if( sem.take(time_scope) )
    {
     Mutex::Lock lock(mutex);

     Slot *slot=slots+done_ind;

     done_ind=NextInd(done_ind);
     done_count--;
     free_count++;

     if( !slot->error )
       {
        pbuf=std::move(slot->pbuf);

        remaining_len-=slot->len;

        return slot->getRange();
       }
    }
  else
    {
     setError(FileError_ReadFault);
    }

  pset.cancel_and_wait();

  fail();

  Printf(Exception,"CCore::ScanAsyncFile::underflow() : #;",getError());

  return Nothing;
 }
Пример #3
0
void ScanAsyncFile::complete(Slot *slot)
 {
  ulen ind=Dist(slots,slot);
  ulen delta=0;

  {
   Mutex::Lock lock(mutex);

   slot->done=true;

   if( ind==op_ind )
     {
      while( op_count && slots[op_ind].done )
        {
         op_ind=NextInd(op_ind);
         op_count--;
         done_count++;
         delta++;
        }
     }
  }

  sem.give_many(delta);
 }
Пример #4
0
static void *BeginNewThread(void *voidThread)
{
    AValue *stack;
    AThread *t;
    AInstance *inst;
    void *threadData;
    athread_mutex_t *mutex;
    athread_cond_t *cond;

    /* NOTE: This code is fragile! Be careful when doing modifications because
       trivial changes in ordering of statements etc. may cause rare
       synchronization problems, especially with garbage collection. */

    t = voidThread;

    athread_mutex_lock(&AThreadMutex);

    ADebugStatusMsg(("New os thread (%ld)\n", (long)t));

    /* Each physical thread loops forever and waits for new arguments that
       signal the creation of a new Alore (logical) thread. */
    for (;;) {
        ABool broadcast;

        /* FIX: perhaps gotta wake up something at some place.. no? */

        /* Wait until we are given some arguments that indicate that we should
           start. The current thread is not active at this time, so NumThreads
           doesn't include it. Therefore don't call AAllowBlocking --
           essentially the thread is always frozen. */
        while (ArgBufFirst == ArgBufLast)
            athread_cond_wait(&ArgBufInsertCond, &AThreadMutex);

        /* From this point on, this thread is active. Keep track of the number
           of active threads. */
        ANumThreads++;

        /* Initially all the threads could be frozen. Make sure that the
           thread is not frozen after we start the execution of the thread,
           since otherwise the garbage collector might be active. */
        NumFreezableThreads++;
        DisallowFreezeNoLock(); /* This decrements NumFreezableThreads. */

        /* If another thread may have read the arguments meanwhile, back off
           and try again. */
        if (ArgBufFirst == ArgBufLast) {
            ANumThreads--;
            continue;
        }

        ADebugStatusMsg(("Alore thread started (%ld)\n", (long)t));

        /* Construct a dummy stack frame at the bottom of the thread stack that
           stores information on the thread. */
        stack = t->stackPtr - 7;
        /* The stack frame header is special, because it doesn't have a related
           Alore function. */
        stack[0] = 7 * sizeof(AValue); /* IDEA: Use a macro? */
        stack[1] = A_THREAD_BOTTOM_FUNCTION;
        stack[2] = A_COMPILED_FRAME_FLAG; /* FIX: Is this ok? */
        /* Read the arguments given during Thread object creation and store
           them for future reference. */
        stack[3] = AThreadArgBuffer[3 * ArgBufFirst + 0];
        stack[4] = AThreadArgBuffer[3 * ArgBufFirst + 1];
        stack[5] = AThreadArgBuffer[3 * ArgBufFirst + 2];
        stack[6] = AZero;
        t->stackPtr = stack;

        /* Clear the arguments after they have been read to allow them to be
           reclaimed by the garbage collector. */
        AThreadArgBuffer[3 * ArgBufFirst + 0] = AZero;
        AThreadArgBuffer[3 * ArgBufFirst + 1] = AZero;
        AThreadArgBuffer[3 * ArgBufFirst + 2] = AZero;

        /* Somebody might be waiting for a free slot in the argument buffer
           in order to create a new thread. Wake him up! */
        if (ArgBufFirst == NextInd(ArgBufLast))
            athread_cond_signal(&ArgBufRemoveCond);

        /* Mark a slot in the argument buffer as free. */
        ArgBufFirst = NextInd(ArgBufFirst);

        athread_mutex_unlock(&AThreadMutex);

        /* The thread has been fully initialized. Now start the execution by
           calling the function given as an argument to the thread. Also catch
           any direct exceptions. */
        if (AHandleException(t))
            stack[4] = AError;
        else
            stack[4] = ACallValue(t, stack[4], 1 | A_VAR_ARG_FLAG,
                                    stack + 5);
        t->contextIndex--;

        inst = AValueToInstance(stack[3]);
        threadData = AValueToPtr(inst->member[A_THREAD_DATA]);
        mutex = GetThreadMutex(threadData);
        cond = GetThreadCond(threadData);

        athread_mutex_lock(mutex);

        broadcast = inst->member[A_THREAD_STATE] == AZero;

        inst->member[A_THREAD_STATE] = AIntToValue(1);

        if (AIsError(stack[4])) {
            inst->member[A_THREAD_STATE] = AIntToValue(2);
            stack[4] = t->exception;
            ACreateTracebackArray(t); /* FIX: is this ok..? */
            inst = AValueToInstance(stack[3]);
        }

        if (!ASetInstanceMember(t, inst, A_THREAD_RET_VAL, stack + 4)) {
            inst = AValueToInstance(stack[3]);
            inst->member[A_THREAD_STATE] = AIntToValue(2);
            inst->member[A_THREAD_RET_VAL] = 0 /*MemoryErrorInstance*/;
            /* FIX!! */
        }

        t->stackPtr = stack + 7;

        athread_mutex_lock(&AThreadMutex);

        NumWaitingThreads++;
        ANumThreads--;

        if (AIsFreeze && NumFreezableThreads == ANumThreads - 1)
            athread_cond_signal(&AllFrozenCond);

        ADebugStatusMsg(("Alore thread ended   (%ld)\n", (long)t));

        athread_mutex_unlock(mutex);

        if (broadcast)
            athread_cond_broadcast(cond);
    }

    /* Never reached */

    /* Return a dummy NULL to get rid of a potential compiler warning. */
    return NULL;
}
Пример #5
0
AValue AThreadCreate(AThread *t, AValue *frame)
{
    AThread *newThread;
    athread_t threadId;
    ABool isWaiting;
    AValue *threadData;

    /* Call the thread function always with no arguments. */
    frame[2] = AMakeArray(t, 0);

    threadData = AAllocUnmovable(sizeof(AValue) + THREAD_DATA_SIZE);
    if (threadData == NULL)
        return ARaiseMemoryErrorND(t);

    AInitNonPointerBlockOld(threadData, THREAD_DATA_SIZE);

    *t->tempStack = ANonPointerBlockToValue(threadData);
    ASetMemberDirect(t, frame[0], A_THREAD_DATA, *t->tempStack);
    threadData = AValueToPtr(*t->tempStack);

    if (athread_mutex_init(GetThreadMutex(threadData), NULL)
        || athread_cond_init(GetThreadCond(threadData), NULL))
        return ARaiseMemoryErrorND(t);

    athread_mutex_lock(&AThreadMutex);

    if (NumWaitingThreads > 0) {
        NumWaitingThreads--;
        isWaiting = TRUE;
        AAvoidWarning_M(newThread = NULL);
    } else {
        athread_mutex_unlock(&AThreadMutex);

        newThread = ACreateThread(frame + 3);
        if (newThread == NULL)
            return ARaiseMemoryErrorND(t);

        isWaiting = FALSE;

        athread_mutex_lock(&AThreadMutex);
    }

    /* Wait until the argument buffer is not full. */
    while (ArgBufFirst == NextInd(ArgBufLast)) {
        AllowFreezeNoLock();
        athread_cond_wait(&ArgBufRemoveCond, &AThreadMutex);
        DisallowFreezeNoLock();
    }

    /* Store thread object, function to be executed and arguments. */
    AThreadArgBuffer[3 * ArgBufLast    ] = frame[0];
    AThreadArgBuffer[3 * ArgBufLast + 1] = frame[1];
    AThreadArgBuffer[3 * ArgBufLast + 2] = frame[2];

    ArgBufLast = NextInd(ArgBufLast);

    athread_mutex_unlock(&AThreadMutex);

    if (isWaiting)
        athread_cond_signal(&ArgBufInsertCond);
    else {
        int result = athread_create(&threadId, BeginNewThread, newThread);
        if (result)
            return ARaiseMemoryErrorND(t); /* FIX: bad */

        /* Perhaps store new thread id somewhere. */
    }

    return frame[0];
}