int LbqPollQueueElement(PLINKED_BLOCKING_QUEUE queueHead, void** data) {
    PLINKED_BLOCKING_QUEUE_ENTRY entry;
    
    if (queueHead->head == NULL) {
        return LBQ_NO_ELEMENT;
    }
    
    PltLockMutex(&queueHead->mutex);
    
    if (queueHead->head == NULL) {
        PltUnlockMutex(&queueHead->mutex);
        return LBQ_NO_ELEMENT;
    }
    
    entry = queueHead->head;
    queueHead->head = entry->flink;
    queueHead->currentSize--;
    if (queueHead->head == NULL) {
        LC_ASSERT(queueHead->currentSize == 0);
        queueHead->tail = NULL;
        PltClearEvent(&queueHead->containsDataEvent);
    }
    else {
        LC_ASSERT(queueHead->currentSize != 0);
        queueHead->head->blink = NULL;
    }
    
    *data = entry->data;
    
    PltUnlockMutex(&queueHead->mutex);
    
    return LBQ_SUCCESS;
}
int LbqOfferQueueItem(PLINKED_BLOCKING_QUEUE queueHead, void* data, PLINKED_BLOCKING_QUEUE_ENTRY entry) {
	entry->flink = NULL;
	entry->data = data;

	PltLockMutex(&queueHead->mutex);

	if (queueHead->currentSize == queueHead->sizeBound) {
		PltUnlockMutex(&queueHead->mutex);
		return LBQ_BOUND_EXCEEDED;
	}

	if (queueHead->head == NULL) {
		LC_ASSERT(queueHead->currentSize == 0);
		LC_ASSERT(queueHead->tail == NULL);
		queueHead->head = entry;
		queueHead->tail = entry;
		entry->blink = NULL;
	}
	else {
		LC_ASSERT(queueHead->currentSize >= 1);
		LC_ASSERT(queueHead->head != NULL);
		queueHead->tail->flink = entry;
		entry->blink = queueHead->tail;
		queueHead->tail = entry;
	}

	queueHead->currentSize++;

	PltUnlockMutex(&queueHead->mutex);

	PltSetEvent(&queueHead->containsDataEvent);

	return LBQ_SUCCESS;
}
Beispiel #3
0
static void requestInvalidateReferenceFrames(void) {
    long long payload[3];
    PQUEUED_FRAME_INVALIDATION_TUPLE qfit;

    LC_ASSERT(VideoCallbacks.capabilities & CAPABILITY_REFERENCE_FRAME_INVALIDATION);

    if (!getNextFrameInvalidationTuple(&qfit)) {
        return;
    }

    LC_ASSERT(qfit->startFrame <= qfit->endFrame);

    payload[0] = qfit->startFrame;
    payload[1] = qfit->endFrame;
    payload[2] = 0;

    // Aggregate all lost frames into one range
    do {
        LC_ASSERT(qfit->endFrame >= payload[1]);
        payload[1] = qfit->endFrame;
        free(qfit);
    } while (getNextFrameInvalidationTuple(&qfit));

    // Send the reference frame invalidation request and read the response
    if (!sendMessageAndDiscardReply(packetTypes[IDX_INVALIDATE_REF_FRAMES],
        payloadLengths[IDX_INVALIDATE_REF_FRAMES], payload)) {
        Limelog("Request Invaldiate Reference Frames: Transaction failed: %d\n", (int) LastSocketError());
        ListenerCallbacks.connectionTerminated(LastSocketError());
        return;
    }

    Limelog("Invalidate reference frame request sent\n");
}
// newEntry is contained within the packet buffer so we free the whole entry by freeing entry->packet
static int queuePacket(PRTP_REORDER_QUEUE queue, PRTP_QUEUE_ENTRY newEntry, int head, PRTP_PACKET packet) {
    if (queue->nextRtpSequenceNumber != UINT16_MAX) {
        PRTP_QUEUE_ENTRY entry;

        // Don't queue packets we're already ahead of
        if (isBeforeSignedInt(packet->sequenceNumber, queue->nextRtpSequenceNumber, 0)) {
            return 0;
        }

        // Don't queue duplicates either
        entry = queue->queueHead;
        while (entry != NULL) {
            if (entry->packet->sequenceNumber == packet->sequenceNumber) {
                return 0;
            }

            entry = entry->next;
        }
    }

    newEntry->packet = packet;
    newEntry->queueTimeMs = PltGetMillis();
    newEntry->prev = NULL;
    newEntry->next = NULL;

    if (queue->oldestQueuedTimeMs == UINT64_MAX) {
        queue->oldestQueuedTimeMs = newEntry->queueTimeMs;
        queue->oldestQueuedEntry = newEntry;
    }

    if (queue->queueHead == NULL) {
        LC_ASSERT(queue->queueSize == 0);
        queue->queueHead = queue->queueTail = newEntry;
    }
    else if (head) {
        LC_ASSERT(queue->queueSize > 0);
        PRTP_QUEUE_ENTRY oldHead = queue->queueHead;
        newEntry->next = oldHead;
        LC_ASSERT(oldHead->prev == NULL);
        oldHead->prev = newEntry;
        queue->queueHead = newEntry;
    }
    else {
        LC_ASSERT(queue->queueSize > 0);
        PRTP_QUEUE_ENTRY oldTail = queue->queueTail;
        newEntry->prev = oldTail;
        LC_ASSERT(oldTail->next == NULL);
        oldTail->next = newEntry;
        queue->queueTail = newEntry;
    }
    queue->queueSize++;

    return 1;
}
void cleanupPlatform(void) {
    cleanupPlatformSockets();

    LC_ASSERT(thread_head == NULL);

    PltDeleteMutex(&thread_list_lock);
}
void PltCloseThread(PLT_THREAD* thread) {
    PLT_THREAD* current_thread;

    PltLockMutex(&thread_list_lock);

    if (thread_head == thread)
    {
        // Remove the thread from the head
        thread_head = thread_head->next;
    }
    else
    {
        // Find the thread in the list
        current_thread = thread_head;
        while (current_thread != NULL) {
            if (current_thread->next == thread) {
                break;
            }

            current_thread = current_thread->next;
        }

        LC_ASSERT(current_thread != NULL);

        // Unlink this thread
        current_thread->next = thread->next;
    }

    PltUnlockMutex(&thread_list_lock);

#if defined(LC_WINDOWS)
    CloseHandle(thread->termRequested);
    CloseHandle(thread->handle);
#endif
}
static PLT_THREAD* findCurrentThread(void) {
    PLT_THREAD* current_thread;

    PltLockMutex(&thread_list_lock);
    current_thread = thread_head;
    while (current_thread != NULL) {
#if defined(LC_WINDOWS)
        if (current_thread->tid == GetCurrentThreadId()) {
#else
        if (pthread_equal(current_thread->thread, pthread_self())) {
#endif
            break;
        }

        current_thread = current_thread->next;
    }
    PltUnlockMutex(&thread_list_lock);

    LC_ASSERT(current_thread != NULL);
    
    return current_thread;
}
#endif

int PltCreateMutex(PLT_MUTEX* mutex) {
#if defined(LC_WINDOWS)
    *mutex = CreateMutexEx(NULL, NULL, 0, MUTEX_ALL_ACCESS);
    if (!*mutex) {
        return -1;
    }
    return 0;
#else
    return pthread_mutex_init(mutex, NULL);
#endif
}
Beispiel #8
0
/**
 * Parse and set a JIT parameter.
 *
 * Parse a string of the form "<param>=<value>" where <param> must be
 * a JIT parameter (see Jit.h) and <value> must be an integer.
 *
 * @returns whether the parameter was parsed and set successfully.
 */
static bool parseJitParam(int32_t *param, const char *str) {
  /* JIT_P_STRING has the form: `(length of following string)(string)` */
  const char *options = JIT_P_STRING;
  int i;
  for (i = 0; i < JIT_P__MAX; i++) {
    size_t len = *(const uint8_t *)options;
    LC_ASSERT(len > 0);
    if (strncmp(str, options + 1, len) == 0 &&
        str[len] == '=') {
      int32_t value = 0;
      const char *p = &str[len+1];
      while (*p >= '0' && *p <= '9') {
        value = value * 10 + (*p++ - '0');
      }
      if (*p != 0) {
        /* Could not parse complete number. */
        return false;
      }
      /* TODO: Validate range */
      param[i] = value;
      return true;
    }
    options += 1 + len;
  }
  return false;
}
int PltWaitForEvent(PLT_EVENT* event) {
#if defined(LC_WINDOWS)
    DWORD error;
    HANDLE objects[2];

    objects[0] = *event;
    objects[1] = findCurrentThread()->termRequested;
    error = WaitForMultipleObjectsEx(2, objects, FALSE, INFINITE, FALSE);
    if (error == WAIT_OBJECT_0) {
        return PLT_WAIT_SUCCESS;
    }
    else if (error == WAIT_OBJECT_0 + 1) {
        return PLT_WAIT_INTERRUPTED;
    }
    else {
        LC_ASSERT(0);
        return -1;
    }
#else
    pthread_mutex_lock(&event->mutex);
    while (!event->signalled) {
        pthread_cond_wait(&event->cond, &event->mutex);
    }
    pthread_mutex_unlock(&event->mutex);
    
    return PLT_WAIT_SUCCESS;
#endif
}
void PltJoinThread(PLT_THREAD* thread) {
    LC_ASSERT(thread->cancelled);
#if defined(LC_WINDOWS)
    WaitForSingleObjectEx(thread->handle, INFINITE, FALSE);
#else
    pthread_join(thread->thread, NULL);
#endif
}
void PltLockMutex(PLT_MUTEX* mutex) {
#if defined(LC_WINDOWS)
    int err;
    err = WaitForSingleObjectEx(*mutex, INFINITE, FALSE);
    if (err != WAIT_OBJECT_0) {
        LC_ASSERT(FALSE);
    }
#else
    pthread_mutex_lock(mutex);
#endif
}
static void removeEntry(PRTP_REORDER_QUEUE queue, PRTP_QUEUE_ENTRY entry) {
    LC_ASSERT(entry != NULL);
    LC_ASSERT(queue->queueSize > 0);
    LC_ASSERT(queue->queueHead != NULL);
    LC_ASSERT(queue->queueTail != NULL);

    if (queue->queueHead == entry) {
        queue->queueHead = entry->next;
    }
    if (queue->queueTail == entry) {
        queue->queueTail = entry->prev;
    }

    if (entry->prev != NULL) {
        entry->prev->next = entry->next;
    }
    if (entry->next != NULL) {
        entry->next->prev = entry->prev;
    }
    queue->queueSize--;
}
int LbqWaitForQueueElement(PLINKED_BLOCKING_QUEUE queueHead, void** data) {
	PLINKED_BLOCKING_QUEUE_ENTRY entry;
	int err;

	for (;;) {
		err = PltWaitForEvent(&queueHead->containsDataEvent);
		if (err != PLT_WAIT_SUCCESS) {
			return LBQ_INTERRUPTED;
		}

		PltLockMutex(&queueHead->mutex);

		if (queueHead->head == NULL) {
			PltClearEvent(&queueHead->containsDataEvent);
			PltUnlockMutex(&queueHead->mutex);
			continue;
		}

		entry = queueHead->head;
		queueHead->head = entry->flink;
		queueHead->currentSize--;
		if (queueHead->head == NULL) {
			LC_ASSERT(queueHead->currentSize == 0);
			queueHead->tail = NULL;
			PltClearEvent(&queueHead->containsDataEvent);
		}
		else {
			LC_ASSERT(queueHead->currentSize != 0);
			queueHead->head->blink = NULL;
		}

		*data = entry->data;

		PltUnlockMutex(&queueHead->mutex);

		break;
	}

	return LBQ_SUCCESS;
}
// Start the video stream
int startVideoStream(void* rendererContext, int drFlags) {
    int err;

    // This must be called before the decoder thread starts submitting
    // decode units
    LC_ASSERT(NegotiatedVideoFormat != 0);
    VideoCallbacks.setup(NegotiatedVideoFormat, StreamConfig.width,
        StreamConfig.height, StreamConfig.fps, rendererContext, drFlags);

    rtpSocket = bindUdpSocket(RemoteAddr.ss_family, RTP_RECV_BUFFER);
    if (rtpSocket == INVALID_SOCKET) {
        return LastSocketError();
    }

    err = PltCreateThread(ReceiveThreadProc, NULL, &receiveThread);
    if (err != 0) {
        return err;
    }

    if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
        err = PltCreateThread(DecoderThreadProc, NULL, &decoderThread);
        if (err != 0) {
            return err;
        }
    }

    if (ServerMajorVersion == 3) {
        // Connect this socket to open port 47998 for our ping thread
        firstFrameSocket = connectTcpSocket(&RemoteAddr, RemoteAddrLen,
                                            FIRST_FRAME_PORT, FIRST_FRAME_TIMEOUT_SEC);
        if (firstFrameSocket == INVALID_SOCKET) {
            return LastSocketError();
        }
    }

    // Start pinging before reading the first frame so GFE knows where
    // to send UDP data
    err = PltCreateThread(UdpPingThreadProc, NULL, &udpPingThread);
    if (err != 0) {
        return err;
    }

    if (ServerMajorVersion == 3) {
        // Read the first frame to start the flow of video
        err = readFirstFrame();
        if (err != 0) {
            return err;
        }
    }

    return 0;
}
Beispiel #15
0
Closure *
loadClosure(const char *filename,
            FILE *f, const StringTabEntry *strings,
            HashTable *itbls, HashTable *closures)
{
  u4 i;
  u4 magic = fget_u4(f);
  assert(magic == CLOSURE_MAGIC);
  char *clos_name = loadId(f, strings, ".");
  u4 payloadsize = fget_varuint(f);
  char *itbl_name = loadId(f, strings, ".");

  Closure *cl = allocStaticClosure(wordsof(ClosureHeader) + payloadsize);
  Closure *fwd_ref;
  InfoTable* info = HashTable_lookup(itbls, itbl_name);
  LC_ASSERT(info != NULL && info->type != INVALID_OBJECT);

  // Fill in closure payload.  May create forward references to
  // the current closure.
  setInfo(cl, info);
  xfree(itbl_name);
  for (i = 0; i < payloadsize; i++) {
    LD_DBG_PR(1, "Loading payload for: %s [%d]\n", clos_name, i);
    u1 dummy;
    loadLiteral(filename, f, &dummy, &cl->payload[i], strings, itbls, closures);
  }

  fwd_ref = HashTable_lookup(closures, clos_name);
  if (fwd_ref != NULL) {
    LD_DBG_PR(2, "Fixing closure forward ref: %s, %p -> %p\n", clos_name, fwd_ref, cl);
    // fixup forward refs
    void **p, *next;
    for (p = (void**)fwd_ref->payload[0]; p != NULL; p = next) {
      next = *p;
      *p = (void*)cl;
    }

    xfree(fwd_ref);
    HashTable_update(closures, clos_name, cl);
    // The key has been allocated by whoever installed the first
    // forward reference.
    xfree(clos_name);

  } else {

    HashTable_insert(closures, clos_name, cl);

  }
  return cl;
}
SOCKET bindUdpSocket(int addrfamily) {
	SOCKET s;
    struct sockaddr_storage addr;
	int val;
	int err;

    LC_ASSERT(addrfamily == AF_INET || addrfamily == AF_INET6);
    
	s = socket(addrfamily, SOCK_DGRAM, IPPROTO_UDP);
	if (s == INVALID_SOCKET) {
        Limelog("socket() failed: %d\n", (int)LastSocketError());
		return INVALID_SOCKET;
	}

	memset(&addr, 0, sizeof(addr));
    addr.ss_family = addrfamily;
	if (bind(s, (struct sockaddr*) &addr,
             addrfamily == AF_INET ?
                sizeof(struct sockaddr_in) :
                sizeof(struct sockaddr_in6)) == SOCKET_ERROR) {
		err = LastSocketError();
        Limelog("bind() failed: %d\n", err);
		closesocket(s);
		SetLastSocketError(err);
		return INVALID_SOCKET;
	}
    
#ifdef LC_DARWIN
    // Disable SIGPIPE on iOS
    val = 1;
    setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (char* )&val, sizeof(val));
#endif

    // Set the receive buffer to 64KB by default
	val = 65536;
	setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*) &val, sizeof(val));

	return s;
}
Beispiel #17
0
// This shim callback runs the client's connectionTerminated() callback on a
// separate thread. This is neccessary because other internal threads directly
// invoke this callback. That can result in a deadlock if the client
// calls LiStopConnection() in the callback when the cleanup code
// attempts to join the thread that the termination callback (and LiStopConnection)
// is running on.
static void ClInternalConnectionTerminated(long errorCode)
{
    int err;

    // Avoid recursion and issuing multiple callbacks
    if (alreadyTerminated) {
        return;
    }

    alreadyTerminated = 1;

    // Invoke the termination callback on a separate thread
    err = PltCreateThread(terminationCallbackThreadFunc, NULL, &terminationCallbackThread);
    if (err != 0) {
        // Nothing we can safely do here, so we'll just assert on debug builds
        Limelog("Failed to create termination thread: %d\n", err);
        LC_ASSERT(err == 0);
    }

    // Close the thread handle since we can never wait on it
    PltCloseThread(&terminationCallbackThread);
}
Beispiel #18
0
InfoTable *
loadInfoTable(const char *filename,
              FILE *f, const StringTabEntry *strings,
              HashTable *itbls, HashTable *closures)
{
  u4 magic = fget_u4(f);
  assert(magic == INFO_MAGIC);

  char *itbl_name = loadId(f, strings, ".");
  u2 cl_type = fget_varuint(f);
  InfoTable *new_itbl = NULL;
  FwdRefInfoTable *old_itbl = HashTable_lookup(itbls, itbl_name);

  if (old_itbl && old_itbl->i.type != INVALID_OBJECT) {
    fprintf(stderr, "ERROR: Duplicate info table: %s\n",
            itbl_name);
    exit(1);
  }

  switch (cl_type) {
  case CONSTR:
    // A statically allocated constructor
    {
      ConInfoTable *info = allocInfoTable(wordsof(ConInfoTable));
      info->i.type = cl_type;
      info->i.tagOrBitmap = fget_varuint(f);  // tag
      Word sz = fget_varuint(f);
      assert(sz <= 32);
      info->i.size = sz;
      info->i.layout.bitmap = sz > 0 ? fget_u4(f) : 0;
      // info->i.layout.payload.ptrs = fget_varuint(f);
      // info->i.layout.payload.nptrs = fget_varuint(f);
      info->name = loadId(f, strings, ".");
      new_itbl = (InfoTable*)info;
    }
    break;
  case FUN:
    {
      FuncInfoTable *info = allocInfoTable(wordsof(FuncInfoTable));
      info->i.type = cl_type;
      info->i.tagOrBitmap = 0; // TODO: anything useful to put in here?
      Word sz = fget_varuint(f);
      assert(sz <= 32);
      info->i.size = sz;
      info->i.layout.bitmap = sz > 0 ? fget_u4(f) : 0;
      info->name = loadId(f, strings, ".");
      loadCode(filename, f, &info->code, strings, itbls, closures);
      new_itbl = (InfoTable*)info;
    }
    break;
  case CAF:
  case THUNK:
    {
      ThunkInfoTable *info = allocInfoTable(wordsof(ThunkInfoTable));
      info->i.type = cl_type;
      info->i.tagOrBitmap = 0; // TODO: anything useful to put in here?
      Word sz = fget_varuint(f);
      assert(sz <= 32);
      info->i.size = sz;
      info->i.layout.bitmap = sz > 0 ? fget_u4(f) : 0;
      info->name = loadId(f, strings, ".");
      loadCode(filename, f, &info->code, strings, itbls, closures);
      new_itbl = (InfoTable*)info;
    }
    break;
  default:
    fprintf(stderr, "ERROR: Unknown info table type (%d)", cl_type);
    exit(1);
  }
  // new_itbl is the new info table.  There may have been forward
  // references (even during loading the code for this info table).
  if (old_itbl != NULL) {
    LD_DBG_PR(1, "Fixing itable forward reference for: %s, %p\n", itbl_name, new_itbl);
    void **p, *next;
    LC_ASSERT(old_itbl->i.type == INVALID_OBJECT);

    for (p = old_itbl->next; p != NULL; p = next) {
      next = *p;
      *p = (void*)new_itbl;
    }

    // TODO: fixup forward refs
    xfree(old_itbl);
    HashTable_update(itbls, itbl_name, new_itbl);
    xfree(itbl_name);
  } else {
    HashTable_insert(itbls, itbl_name, new_itbl);
  }

  return new_itbl;
}
Beispiel #19
0
int
irEngine(Capability *cap, Fragment *F)
{
  static Inst disp[] = {
#define IRIMPL(name, f, o1, o2)  &&op_##name,
    IRDEF(IRIMPL)
#undef IRIMPL
    &&stop
  };

  
  IRRef ref;
  Thread *T = cap->T;
  Word nphis = F->nphis;
  Word *base = T->base - 1;
  Word szins = F->nins - F->nk;
  Word vals_[szins + nphis];
  Word *phibuf = &vals_[szins]; /* For parallel copy of PHI nodes */
  Word *vals = vals_ - (int)F->nk;
       
  IRIns *pc = F->ir + REF_FIRST;
  IRRef pcref = REF_FIRST;
  IRIns *pcmax = F->ir + F->nins;
  IRIns *pcloop = F->nloop ? F->ir + F->nloop + 1 : pc;
  //int count = 100;

  DBG_PR("*** Executing trace.\n"
         "***   base  = %p\n"
         "***   pc    = %p\n"
         "***   pcmax = %p (%d)\n"
         "***   loop  = %p (%d)\n",
         base, pc, pcmax, (int)(pcmax - pc), pcloop, (int)(pcloop - pc));

  for (ref = F->nk; ref < REF_BIAS; ref++) {
    switch (IR(ref)->o) {
    case IR_KINT:   vals[ref] = (Word)IR(ref)->i; break;
    case IR_KBASEO: vals[ref] = (Word)(T->base + IR(ref)->i); break;
    case IR_KWORD:  vals[ref] = (Word)(F->kwords[IR(ref)->u]); break;
    default:
      LC_ASSERT(0); break;
    }
    DBG_LVL(2, "%d, %" FMT_WordX "\n", ref - REF_BIAS, vals[ref]);
  }
  vals[REF_BASE] = (Word)base;

  goto *disp[pc->o];

# define DISPATCH_NEXT \
  if (irt_type(pc->t) != IRT_VOID && pc->o != IR_PHI) { \
    if (irt_type(pc->t) == IRT_I32) \
      DBG_LVL(2, "         ===> %" FMT_Int "\n", vals[pcref]); \
    else \
      DBG_LVL(2, "         ===> 0x%" FMT_WordX "\n", vals[pcref]); } \
  ++pc; ++pcref; \
  if (LC_UNLIKELY(pc >= pcmax)) { pc = pcloop; pcref = F->nloop + 1; } \
  if (pc->o != IR_NOP) { \
    DBG_LVL(2, "[%d] ", pcref - REF_BIAS); \
    IF_DBG_LVL(2, printIR(F, *pc)); } \
  goto *disp[pc->o]

 op_NOP:
 op_FRAME:
 op_RET:
 op_LOOP:
  DISPATCH_NEXT;

 op_PHI:
  {
    /* PHI nodes represent parallel assignments, so as soon as we
       discover the first PHI node, we perform all assignments in
       parallel. */
    LC_ASSERT(nphis > 0);
    u2 i;
    DBG_LVL(3, "             ( ");
    for (i = 0; i < nphis; i++) {
      DBG_LVL(3, "%d ", irref_int(pc[i].op2));
      phibuf[i] = vals[pc[i].op2];
    }
    DBG_LVL(3, ") --> ( ");
    for (i = 0; i < nphis; i++) {
      DBG_LVL(3, "%d ", irref_int(pc[i].op1));
      vals[pc[i].op1] = phibuf[i];
    }
    DBG_LVL(3, ")  [%d phis]\n", (int)nphis);
    pc += nphis - 1;
    //vals[pc->op1] = vals[pc->op2];
    DISPATCH_NEXT;
  }

 op_LT:
  recordEvent(EV_CMP, 0);
  if (!((WordInt)vals[pc->op1] < (WordInt)vals[pc->op2]))
    goto guard_failed;
  DISPATCH_NEXT;

 op_GE:
  recordEvent(EV_CMP, 0);
  if (!((WordInt)vals[pc->op1] >= (WordInt)vals[pc->op2]))
    goto guard_failed;
  DISPATCH_NEXT;

 op_LE:
  recordEvent(EV_CMP, 0);
  if (!((WordInt)vals[pc->op1] <= (WordInt)vals[pc->op2]))
    goto guard_failed;
  DISPATCH_NEXT;

 op_GT:
  recordEvent(EV_CMP, 0);
  if (!((WordInt)vals[pc->op1] > (WordInt)vals[pc->op2]))
    goto guard_failed;
  DISPATCH_NEXT;

 op_EQ:
  recordEvent(EV_CMP, 0);
  if (!((WordInt)vals[pc->op1] == (WordInt)vals[pc->op2])) {
    goto guard_failed;
  }
  DISPATCH_NEXT;

 op_NE:
  recordEvent(EV_CMP, 0);
  if (!((WordInt)vals[pc->op1] != (WordInt)vals[pc->op2]))
    goto guard_failed;
  DISPATCH_NEXT;

 op_ADD:
  recordEvent(EV_ALU, 0);
  vals[pcref] = vals[pc->op1] + vals[pc->op2];
  DISPATCH_NEXT;

 op_SUB:
  recordEvent(EV_ALU, 0);
  vals[pcref] = vals[pc->op1] - vals[pc->op2];
  DISPATCH_NEXT;

 op_MUL:
  recordEvent(EV_MUL, 0);
  vals[pcref] = (WordInt)vals[pc->op1] * (WordInt)vals[pc->op2];
  DISPATCH_NEXT;

 op_DIV:
  recordEvent(EV_REMDIV, 0);
  if (LC_LIKELY(vals[pc->op2] != 0))
    vals[pcref] = (WordInt)vals[pc->op1] / (WordInt)vals[pc->op2];
  else
    LC_ASSERT(0);
  DISPATCH_NEXT;

 op_REM:
  recordEvent(EV_REMDIV, 0);
  if (LC_LIKELY(vals[pc->op2] != 0))
    vals[pcref] = (WordInt)vals[pc->op1] % (WordInt)vals[pc->op2];
  else
    LC_ASSERT(0);
  DISPATCH_NEXT;

 op_FREF:
  vals[pcref] = (Word)(((Closure*)vals[pc->op1])->payload + (pc->op2 - 1));
  DISPATCH_NEXT;

 op_FLOAD:
  recordEvent(EV_LOAD, 0);
  vals[pcref] = *((Word*)vals[pc->op1]);
  DISPATCH_NEXT;

 op_SLOAD:
  recordEvent(EV_LOAD, 0);
  vals[pcref] = base[pc->op1];
  DISPATCH_NEXT;

 op_ILOAD:
  recordEvent(EV_LOAD, 0);
  vals[pcref] = (Word)getInfo(vals[pc->op1]);
  DISPATCH_NEXT;

 op_NEW:
  if (!ir_issunken(pc)) {
    // do actual allocation on trace
    HeapInfo *hp = &F->heap[pc->op2];
    int j;
    recordEvent(EV_ALLOC, hp->nfields + 1);
    Closure *cl = allocClosure(wordsof(ClosureHeader) + hp->nfields);
    setInfo(cl, (InfoTable*)vals[pc->op1]);
    for (j = 0; j < hp->nfields; j++) {
      cl->payload[j] = vals[getHeapInfoField(F, hp, j)];
    }
    vals[pcref] = (Word)cl;
  } else {
    vals[pcref] = 0;  // to trigger an error if accessed
  }
  DISPATCH_NEXT;

 op_UPDATE:
  {
    recordEvent(EV_UPDATE, 0);
    Closure *oldnode = (Closure *)vals[pc->op1];
    Closure *newnode = (Closure *)base[pc->op2];
    setInfo(oldnode, (InfoTable*)&stg_IND_info);
    oldnode->payload[0] = (Word)newnode;
    DISPATCH_NEXT;
  }

 op_RLOAD:
 op_FSTORE:
 op_RENAME:


 op_BNOT: op_BAND: op_BOR: op_BXOR:
 op_BSHL: op_BSHR: op_BSAR:
 op_BROL: op_BROR:

  // These should never be executed.
 op_BASE:
 op_KINT:
 op_KWORD:
 op_KBASEO:
  LC_ASSERT(0);

 guard_failed:
  DBG_PR("Exiting at %d\n", pcref - REF_BIAS);

  {
    int i;
    SnapShot *snap = 0;
    SnapEntry *se;
    for (i = 0; i < F->nsnap; i++) {
      if (F->snap[i].ref == pcref) {
        snap = &F->snap[i];
        break;
      }
    }
    LC_ASSERT(snap != 0);
    snap->count++;
    se = F->snapmap + snap->mapofs;
    DBG_PR("Snapshot: %d, Snap entries: %d, slots = %d\n",
           i, snap->nent, snap->nslots);
    recordEvent(EV_EXIT, snap->nent);
    for (i = 0; i < snap->nent; i++, se++) {
      BCReg s = snap_slot(*se);
      IRRef r = snap_ref(*se);

      DBG_PR("base[%d] = ", s - 1);
      base[s] = restoreValue(F, vals, r);

      IF_DBG_LVL(1, printSlot(stderr, base + s); fprintf(stderr, "\n"));
      //DBG_PR("0x%" FMT_WordX "\n", base[s]);
    }
    DBG_PR("Base slot: %d\n", se[1]);
    //    se[1] = 
    T->pc = (BCIns *)F->startpc + (int)se[0];
    T->base = base + se[1];
    T->top = base + snap->nslots;
    //printFrame(T->base, T->top);
    return 0;
  }

 stop:
  return 1;
}
Beispiel #20
0
/* Stop the connection by undoing the step at the current stage and those before it */
void LiStopConnection(void) {
    // Disable termination callbacks now
    alreadyTerminated = 1;
    
	if (stage == STAGE_INPUT_STREAM_START) {
		Limelog("Stopping input stream...");
		stopInputStream();
		stage--;
		Limelog("done\n");
	}
	if (stage == STAGE_AUDIO_STREAM_START) {
		Limelog("Stopping audio stream...");
		stopAudioStream();
		stage--;
		Limelog("done\n");
	}
	if (stage == STAGE_VIDEO_STREAM_START) {
		Limelog("Stopping video stream...");
		stopVideoStream();
		stage--;
		Limelog("done\n");
	}
	if (stage == STAGE_CONTROL_STREAM_START) {
		Limelog("Stopping control stream...");
		stopControlStream();
		stage--;
		Limelog("done\n");
	}
	if (stage == STAGE_INPUT_STREAM_INIT) {
		Limelog("Cleaning up input stream...");
		destroyInputStream();
		stage--;
		Limelog("done\n");
	}
	if (stage == STAGE_AUDIO_STREAM_INIT) {
		Limelog("Cleaning up audio stream...");
		destroyAudioStream();
		stage--;
		Limelog("done\n");
	}
	if (stage == STAGE_VIDEO_STREAM_INIT) {
		Limelog("Cleaning up video stream...");
		destroyVideoStream();
		stage--;
		Limelog("done\n");
	}
	if (stage == STAGE_CONTROL_STREAM_INIT) {
		Limelog("Cleaning up control stream...");
		destroyControlStream();
		stage--;
		Limelog("done\n");
	}
	if (stage == STAGE_RTSP_HANDSHAKE) {
		Limelog("Terminating RTSP handshake...");
		terminateRtspHandshake();
		stage--;
		Limelog("done\n");
	}
    if (stage == STAGE_NAME_RESOLUTION) {
        // Nothing to do
        stage--;
    }
	if (stage == STAGE_PLATFORM_INIT) {
		Limelog("Cleaning up platform...");
		cleanupPlatform();
		stage--;
		Limelog("done\n");
	}
	LC_ASSERT(stage == STAGE_NONE);
}
Beispiel #21
0
/* Starts the connection to the streaming machine */
int LiStartConnection(const char* host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
	PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks,
	void* renderContext, int drFlags, int _serverMajorVersion) {
	int err;

    ServerMajorVersion = _serverMajorVersion;
    memcpy(&StreamConfig, streamConfig, sizeof(StreamConfig));

	// Replace missing callbacks with placeholders
	fixupMissingCallbacks(&drCallbacks, &arCallbacks, &clCallbacks);
    memcpy(&VideoCallbacks, drCallbacks, sizeof(VideoCallbacks));
    memcpy(&AudioCallbacks, arCallbacks, sizeof(AudioCallbacks));

	// Hook the termination callback so we can avoid issuing a termination callback
	// after LiStopConnection() is called
	originalTerminationCallback = clCallbacks->connectionTerminated;
	memcpy(&ListenerCallbacks, clCallbacks, sizeof(ListenerCallbacks));
    ListenerCallbacks.connectionTerminated = ClInternalConnectionTerminated;
    
    alreadyTerminated = 0;

	Limelog("Initializing platform...");
	ListenerCallbacks.stageStarting(STAGE_PLATFORM_INIT);
	err = initializePlatform();
	if (err != 0) {
		Limelog("failed: %d\n", err);
		ListenerCallbacks.stageFailed(STAGE_PLATFORM_INIT, err);
		goto Cleanup;
	}
	stage++;
	LC_ASSERT(stage == STAGE_PLATFORM_INIT);
	ListenerCallbacks.stageComplete(STAGE_PLATFORM_INIT);
	Limelog("done\n");
    
    Limelog("Resolving host name...");
    ListenerCallbacks.stageStarting(STAGE_NAME_RESOLUTION);
    err = resolveHostName(host);
    if (err != 0) {
        Limelog("failed: %d\n", err);
        ListenerCallbacks.stageFailed(STAGE_NAME_RESOLUTION, err);
        goto Cleanup;
    }
    stage++;
    LC_ASSERT(stage == STAGE_NAME_RESOLUTION);
    ListenerCallbacks.stageComplete(STAGE_NAME_RESOLUTION);
    Limelog("done\n");

	Limelog("Starting RTSP handshake...");
	ListenerCallbacks.stageStarting(STAGE_RTSP_HANDSHAKE);
	err = performRtspHandshake();
	if (err != 0) {
		Limelog("failed: %d\n", err);
		ListenerCallbacks.stageFailed(STAGE_RTSP_HANDSHAKE, err);
		goto Cleanup;
	}
	stage++;
	LC_ASSERT(stage == STAGE_RTSP_HANDSHAKE);
	ListenerCallbacks.stageComplete(STAGE_RTSP_HANDSHAKE);
	Limelog("done\n");

	Limelog("Initializing control stream...");
	ListenerCallbacks.stageStarting(STAGE_CONTROL_STREAM_INIT);
	err = initializeControlStream();
	if (err != 0) {
		Limelog("failed: %d\n", err);
		ListenerCallbacks.stageFailed(STAGE_CONTROL_STREAM_INIT, err);
		goto Cleanup;
	}
	stage++;
	LC_ASSERT(stage == STAGE_CONTROL_STREAM_INIT);
	ListenerCallbacks.stageComplete(STAGE_CONTROL_STREAM_INIT);
	Limelog("done\n");

	Limelog("Initializing video stream...");
	ListenerCallbacks.stageStarting(STAGE_VIDEO_STREAM_INIT);
	initializeVideoStream();
	stage++;
	LC_ASSERT(stage == STAGE_VIDEO_STREAM_INIT);
	ListenerCallbacks.stageComplete(STAGE_VIDEO_STREAM_INIT);
	Limelog("done\n");

	Limelog("Initializing audio stream...");
	ListenerCallbacks.stageStarting(STAGE_AUDIO_STREAM_INIT);
	initializeAudioStream();
	stage++;
	LC_ASSERT(stage == STAGE_AUDIO_STREAM_INIT);
	ListenerCallbacks.stageComplete(STAGE_AUDIO_STREAM_INIT);
	Limelog("done\n");

	Limelog("Initializing input stream...");
	ListenerCallbacks.stageStarting(STAGE_INPUT_STREAM_INIT);
	initializeInputStream(streamConfig->remoteInputAesKey, sizeof(streamConfig->remoteInputAesKey),
		streamConfig->remoteInputAesIv, sizeof(streamConfig->remoteInputAesIv));
	stage++;
	LC_ASSERT(stage == STAGE_INPUT_STREAM_INIT);
	ListenerCallbacks.stageComplete(STAGE_INPUT_STREAM_INIT);
	Limelog("done\n");

	Limelog("Starting control stream...");
	ListenerCallbacks.stageStarting(STAGE_CONTROL_STREAM_START);
	err = startControlStream();
	if (err != 0) {
		Limelog("failed: %d\n", err);
		ListenerCallbacks.stageFailed(STAGE_CONTROL_STREAM_START, err);
		goto Cleanup;
	}
	stage++;
	LC_ASSERT(stage == STAGE_CONTROL_STREAM_START);
	ListenerCallbacks.stageComplete(STAGE_CONTROL_STREAM_START);
	Limelog("done\n");

	Limelog("Starting video stream...");
	ListenerCallbacks.stageStarting(STAGE_VIDEO_STREAM_START);
	err = startVideoStream(renderContext, drFlags);
	if (err != 0) {
		Limelog("Video stream start failed: %d\n", err);
		ListenerCallbacks.stageFailed(STAGE_VIDEO_STREAM_START, err);
		goto Cleanup;
	}
	stage++;
	LC_ASSERT(stage == STAGE_VIDEO_STREAM_START);
	ListenerCallbacks.stageComplete(STAGE_VIDEO_STREAM_START);
	Limelog("done\n");

	Limelog("Starting audio stream...");
	ListenerCallbacks.stageStarting(STAGE_AUDIO_STREAM_START);
	err = startAudioStream();
	if (err != 0) {
		Limelog("Audio stream start failed: %d\n", err);
		ListenerCallbacks.stageFailed(STAGE_AUDIO_STREAM_START, err);
		goto Cleanup;
	}
	stage++;
	LC_ASSERT(stage == STAGE_AUDIO_STREAM_START);
	ListenerCallbacks.stageComplete(STAGE_AUDIO_STREAM_START);
	Limelog("done\n");

	Limelog("Starting input stream...");
	ListenerCallbacks.stageStarting(STAGE_INPUT_STREAM_START);
	err = startInputStream();
	if (err != 0) {
		Limelog("Input stream start failed: %d\n", err);
		ListenerCallbacks.stageFailed(STAGE_INPUT_STREAM_START, err);
		goto Cleanup;
	}
	stage++;
	LC_ASSERT(stage == STAGE_INPUT_STREAM_START);
	ListenerCallbacks.stageComplete(STAGE_INPUT_STREAM_START);
	Limelog("done\n");

	ListenerCallbacks.connectionStarted();

Cleanup:
	return err;
}
Beispiel #22
0
// Load the module and
Module *
loadModuleHeader(FILE *f, const char *filename)
{
  Module *mdl;
  char magic[5];
  u2 major, minor;
  u4 flags;
  u4 secmagic;
  u4 i;

  LC_ASSERT(f != NULL);

  fread(magic, 4, 1, f);
  magic[4] = '\0';
  if (strcmp(magic, "KHCB") != 0) {
    fprintf(stderr, "ERROR: Module '%s' is not a bytecode file. %s\n",
            filename, magic);
    exit(1);
  }

  mdl = xmalloc(sizeof(Module));

  major = fget_u2(f);
  minor = fget_u2(f);

  if (major != VERSION_MAJOR || minor != VERSION_MINOR) {
    fprintf(stderr, "ERROR: Module '%s' version mismatch.  Version: %d.%d, Expected: %d.%d\n",
            filename, major, minor, VERSION_MAJOR, VERSION_MINOR);
    exit(1);
  }

  flags = fget_u4(f);
  mdl->numStrings    = fget_u4(f);
  mdl->numInfoTables = fget_u4(f);
  mdl->numClosures   = fget_u4(f);
  mdl->numImports    = fget_u4(f);

  //printf("strings = %d, itbls = %d, closures = %d\n",
  //       mdl->numStrings, mdl->numInfoTables, mdl->numClosures);

  // String table starts with a 4 byte magic.
  secmagic = fget_u4(f);
  assert(secmagic == STR_SEC_HDR_MAGIC);

  mdl->strings = xmalloc(sizeof(StringTabEntry) * mdl->numStrings);
  for (i = 0; i < mdl->numStrings; i++) {
    loadStringTabEntry(f, &mdl->strings[i]);
  }

  //printStringTable(mdl->strings, mdl->numStrings);

  mdl->name = loadId(f, mdl->strings, ".");
  // printf("mdl name = %s\n", mdl->name);

  mdl->imports = xmalloc(sizeof(*mdl->imports) * mdl->numImports);
  for (i = 0; i < mdl->numImports; i++) {
    mdl->imports[i] = loadId(f, mdl->strings, ".");
    // printf("import: %s\n", mdl->imports[i]);
  }

  return mdl;
}