Esempio n. 1
0
static void sim_fire_events(struct simulator *sim) {
  struct sig_hook *hooks, *h, *t;
  picos_t orig_target;
  int is_target_time;
  hooks = sim->hooks;
  sim->hooks = 0;
  sim->calling_hooks = 1;
  DL_FOREACH_SAFE(hooks, h, t) {
    is_target_time = (h->time && h->time <= sim->picos);
    if (is_target_time || (sim->any_event && bv_and_reduce(&sim->events, &h->signals))) {
      orig_target = h->time;
      if (h->cb(sim, h)) {
        h->time = 0;
        DL_DELETE(hooks, h);
      } else {
        if (h->time <= sim->picos) {
          /* disable times in the past */
          h->time = 0;
        }
        if (h->time != orig_target) {
          /* reschedule if time changed */
          DL_DELETE(hooks, h);
          DL_APPEND(sim->hooks, h);
        }
      }
    }
  }
Esempio n. 2
0
/*-----------------------------------------------------------------------------
*   free
*----------------------------------------------------------------------------*/
void m_free_( void *memptr, char *file, int lineno )
{
    MemBlock *block = NULL;
    Bool result;

    init_module();

    /* if input is NULL, do nothing */
    if ( memptr == NULL )
        return;

    block = find_block( memptr, file, lineno );
    check( block, "memory free at %s:%d failed", file, lineno );

    /* delete from list to avoid recursion atexit() if overflow */
    DL_DELETE(g_mem_blocks, block );

    /* check fences */
    result = check_fences( block );
    check( result, "memory free at %s:%d failed", file, lineno );

error:
    /* delete memory blocks */
    if ( block ) {
        if ( block->destructor )			/* destroy children */
            block->destructor( memptr );	/* user destructor */

        free( block );						/* destroy itself */
    }
}
Esempio n. 3
0
void ircd_client_free(struct ircd_client* const client)
{
	if (! client)
		return;

	if (client->info_length > 0 && client->info_written < client->info_length)
		(void) ssl_close_notify(&client->ssl_ctx);

	(void) ssl_free(&client->ssl_ctx);

	if (client->ev_t)
		(void) event_free(client->ev_t);

	if (client->ev_r)
		(void) event_free(client->ev_r);

	if (client->ev_w)
		(void) event_free(client->ev_w);

	if (client->fd > -1)
		(void) close(client->fd);

	DL_DELETE(ircd_clients, client);
	free(client);
}
Esempio n. 4
0
int main(int argc, char *argv[]) {
    el *name, *tmp;

    char linebuf[BUFLEN];
    FILE *file;

    if ( (file = fopen( "test11.dat", "r" )) == NULL ) {
        perror("can't open: "); 
        exit(-1);
    }

    while (fgets(linebuf,BUFLEN,file) != NULL) {
        if ( (name = (el*)malloc(sizeof(el))) == NULL) exit(-1);
        strncpy(name->bname,linebuf,BUFLEN);
        DL_APPEND(head, name);
    }
    DL_SORT(head, namecmp);
    DL_FOREACH(head,tmp) printf("%s", tmp->bname);

    /* now delete the list head */
    printf("deleting head %shead->prev: %s", head->bname, head->prev->bname);
    DL_DELETE(head,head);
    DL_FOREACH(head,tmp) printf("%s", tmp->bname);

    fclose(file);

    return 0;
}
Esempio n. 5
0
void ucm_section_free_list(struct ucm_section *sections)
{
	struct ucm_section *section;
	DL_FOREACH(sections, section) {
		DL_DELETE(sections, section);
		ucm_section_free(section);
	}
Esempio n. 6
0
int MPIR_T_pvar_handle_free_impl(MPI_T_pvar_session session, MPI_T_pvar_handle *handle)
{
    int mpi_errno = MPI_SUCCESS;
    MPIR_T_pvar_handle_t *hnd = *handle;

    DL_DELETE(session->hlist, hnd);

    /* Unlink handle from pvar if it is a watermark */
    if (MPIR_T_pvar_is_watermark(hnd)) {
        MPIR_T_pvar_watermark_t *mark = (MPIR_T_pvar_watermark_t *)hnd->addr;
        if (MPIR_T_pvar_is_first(hnd)) {
            mark->first_used = 0;
            mark->first_started = 0;
        } else {
            MPIR_Assert(mark->hlist);
            if (mark->hlist == hnd) {
                /* hnd happens to be the head */
                mark->hlist = hnd->next2;
                if (mark->hlist != NULL)
                    mark->hlist->prev2 = mark->hlist;
            } else {
                hnd->prev2->next2 = hnd->next2;
                if (hnd->next2 != NULL)
                    hnd->next2->prev2 = hnd->prev2;
            }
        }
    }

    MPL_free(hnd);
    *handle = MPI_T_PVAR_HANDLE_NULL;

    return mpi_errno;
}
Esempio n. 7
0
int main(int argc, char *argv[]) {
    el *name, *elt, *tmp, etmp;
    int i;
    example_user_t *user, *users=NULL;

    char linebuf[BUFLEN];
    FILE *file;

    UT_string *s;
    char binary[] = "\xff\xff";

    if ( (file = fopen( "test11.dat", "r" )) == NULL ) {
        perror("can't open: ");
        exit(-1);
    }

    while (fgets(linebuf,BUFLEN,file) != NULL) {
        if ( (name = (el*)malloc(sizeof(el))) == NULL) exit(-1);
        strncpy(name->bname,linebuf,BUFLEN);
        DL_APPEND(head, name);
    }
    DL_SORT(head, namecmp);
    DL_FOREACH(head,elt) printf("%s", elt->bname);

    memcpy(&etmp.bname, "WES\n", 5);
    DL_SEARCH(head,elt,&etmp,namecmp);
    if (elt) printf("found %s\n", elt->bname);

    /* now delete each element, use the safe iterator */
    DL_FOREACH_SAFE(head,elt,tmp) {
      DL_DELETE(head,elt);
    }
Esempio n. 8
0
int main(int argc, char *argv[]) {
    el *name, *elt, *tmp, etmp;
    el *head = NULL; /* important- initialize to NULL! */

    char linebuf[BUFLEN];
    FILE *file;

    file = fopen( "test11.dat", "r" );
    if (file == NULL) {
        perror("can't open: ");
        exit(-1);
    }

    while (fgets(linebuf,BUFLEN,file) != NULL) {
        name = (el*)malloc(sizeof(el));
        if (name == NULL) exit(-1);
        strncpy(name->bname,linebuf,sizeof(name->bname));
        DL_APPEND(head, name);
    }
    DL_SORT(head, namecmp);
    DL_FOREACH(head,elt) printf("%s", elt->bname);

    memcpy(etmp.bname, "WES\n", 5UL);
    DL_SEARCH(head,elt,&etmp,namecmp);
    if (elt != NULL) printf("found %s\n", elt->bname);

    /* now delete each element, use the safe iterator */
    DL_FOREACH_SAFE(head,elt,tmp) {
      DL_DELETE(head,elt);
    }
Esempio n. 9
0
/* Remove an item from the WQ. Currently, this immediately attempts
 * to remove the item at the head of the list, and will fail if there are
 * no items in the list.
 *
 * It is your task to make it so that this function will wait until the queue
 * contains at least one item, then remove that item from the list and
 * return it. */
void *wq_pop(wq_t *wq) {
  void *job;
  if (wq->head == NULL)
    return NULL;
  job = wq->head->item;
  DL_DELETE(wq->head,wq->head);
  return job;
}
Esempio n. 10
0
int nextFrame_fifo(mmu *m){
  pteAgent *cur;
  int re;
  cur = m->pageA;
  re = cur->myID;
  DL_DELETE(m->pageA, cur);
  DL_APPEND(m->pageA, cur);
  return m->frames[re];
}
Esempio n. 11
0
void profile_rma_end_all_nbstores()
{
    rma_node_t *rma_node, *tmp;
    if (!profiling_enabled || !(prof_groups & CAFPROF_PUT))
        return;

    DL_FOREACH_SAFE(saved_store_rma_list, rma_node, tmp) {
        PROFILE_PUT_END_REMOTE(rma_node->target, rma_node->rmaid);
        DL_DELETE(saved_store_rma_list, rma_node);
    }
Esempio n. 12
0
/**
 * Clear all data in the linked list of servers reported by metaserver.
 */
void metaserver_clear_data(void)
{
    server_struct *node, *tmp;

    SDL_LockMutex(server_head_mutex);

    DL_FOREACH_SAFE(server_head, node, tmp)
    {
        DL_DELETE(server_head, node);
        metaserver_free(node);
    }
Esempio n. 13
0
/* Remove an item from the WQ. Currently, this immediately attempts
 * to remove the item at the head of the list, and will fail if there are
 * no items in the list.
 *
 * It is your task to make it so that this function will wait until the queue
 * contains at least one item, then remove that item from the list and
 * return it. */
void *wq_pop(wq_t *wq) {
  // OUR CODE HERE
  pthread_mutex_lock(&wq->lock);
  while (wq->head == NULL) {
    pthread_cond_wait(&wq->cv, &wq->lock);
  }
  void *job = wq->head->item;
  DL_DELETE(wq->head,wq->head);
  pthread_mutex_unlock(&wq->lock);
  return job;
}
Esempio n. 14
0
int main() {
    int i;
    el els[10], *e, *tmp, *tmp2;
    for(i=0;i<10;i++) els[i].id='a'+i;

    /* test LL macros */
    printf("LL macros\n");
    LL_APPEND(head,&els[0]);
    LL_APPEND(head,&els[1]);
    LL_APPEND(head,&els[2]);
    LL_FOREACH(head,e)
        printf("%c ", e->id);
    printf("\n");
    LL_SEARCH_SCALAR(head, e, id, 'b');
    if (e) printf("search scalar found b\n");
    LL_SEARCH(head, e, &els[0], eltcmp);
    if (e) printf("search found %c\n",e->id);
    LL_FOREACH_SAFE(head,e,tmp) LL_DELETE(head,e);

    printf("\n");

    /* test DL macros */
    printf("DL macros\n");
    DL_APPEND(head,&els[0]);
    DL_APPEND(head,&els[1]);
    DL_APPEND(head,&els[2]);
    DL_FOREACH(head,e)
        printf("%c ", e->id);
    printf("\n");
    DL_SEARCH_SCALAR(head, e, id, 'b');
    if (e) printf("search scalar found b\n");
    DL_SEARCH(head, e, &els[0], eltcmp);
    if (e) printf("search found %c\n",e->id);
    DL_FOREACH_SAFE(head,e,tmp) DL_DELETE(head,e);
    printf("\n");

    /* test CDL macros */
    printf("CDL macros\n");
    CDL_PREPEND(head,&els[0]);
    CDL_PREPEND(head,&els[1]);
    CDL_PREPEND(head,&els[2]);
    CDL_FOREACH(head,e)
        printf("%c ", e->id);
    printf("\n");
    CDL_SEARCH_SCALAR(head, e, id, 'b');
    if (e) printf("search scalar found b\n");
    CDL_SEARCH(head, e, &els[0], eltcmp);
    if (e) printf("search found %c\n",e->id);
    CDL_FOREACH_SAFE(head,e,tmp,tmp2) CDL_DELETE(head,e);


    return 0;
}
Esempio n. 15
0
void
packetproc_del_pp_ref(struct packetproc *packetproc, uint32_t processor_id, UNUSED_ATTR uint32_t input_id, uint32_t pp_ref) {
    struct pp *pp;
    HASH_FIND(hh, packetproc->pp_map, &processor_id, sizeof(size_t), pp);
    //TODO: check existance

    struct pp_refs *pp_refs;
    DL_SEARCH_SCALAR(pp->processor_refs, pp_refs, ref, pp_ref); /* its enogh to search based on ref,
                                                                   an input  can referred only by one processor */
    //TODO: check existance
    DL_DELETE(pp->processor_refs, pp_refs);
}
Esempio n. 16
0
/**
 * @brief In case of array[index] = 0 assignments the corresponding row is deleted...
 * @param pos
 */
void mkNULL (int pos)
{
	code *c = NULL;
	DL_FOREACH(code_list,c){
		if(c->counter_id == pos)
		{
			DL_DELETE(code_list, c);
			num_of_codes--;
			c = c->next;
			c->counter_id--;
		}
	}
}
Esempio n. 17
0
void cras_bt_transport_destroy(struct cras_bt_transport *transport)
{
	DL_DELETE(transports, transport);

	dbus_connection_unref(transport->conn);

	if (transport->fd >= 0)
		close(transport->fd);

	free(transport->object_path);
	free(transport->configuration);
	free(transport);
}
Esempio n. 18
0
/*
 * Clear all tasks. There may still remain one currently executing task.
 */
void
texasync_clear(void)
{
        SDL_mutexP(storage_mutex);
        {
                while (finished_tasks != NULL) {
                        Task *task = finished_tasks;
                        DL_DELETE(finished_tasks, task);
                        free_task(task);
                        
                        /* Update finished task counter. */
                        assert(num_finished > 0);
                        num_finished--;
                }
                
                while (active_tasks != NULL) {
                        Task *task = active_tasks;
                        DL_DELETE(active_tasks, task);
                        free_task(task);
                }
        }
        SDL_mutexV(storage_mutex);
}
Esempio n. 19
0
void *queue_dequeue(queue_t *queue,int32_t offsetflag)
{
    struct queueitem *item = 0;
    lock_queue(queue);
    if ( queue->list != 0 )
    {
        item = queue->list;
        DL_DELETE(queue->list,item);
        //printf("name.(%s) dequeue.%p list.%p\n",queue->name,item,queue->list);
    }
	portable_mutex_unlock(&queue->mutex);
    if ( item != 0 && offsetflag != 0 )
        return((void *)((long)item + sizeof(struct queueitem)));
    else return(item);
}
/**
 * Free all the services holded by the server
 *
 * @return A HPD error code
 */
int 
free_unsecure_server_services()
{
	ServiceElement *iterator, *tmp;

	if( service_head == NULL )
		return HPD_E_NULL_POINTER;

	DL_FOREACH_SAFE( service_head, iterator, tmp )
	{
		DL_DELETE( service_head, iterator );
		destroy_service_struct( iterator->service );
		destroy_service_element_struct( iterator );
		iterator = NULL;
	}
Esempio n. 21
0
static void
load(const char *filename, uint flags, void *img_data, uint img_size, uintptr_t group, TextureLoaded sync_cb, void *cb_data)
{
        assert(sync_cb != NULL);
        SDL_mutexP(storage_mutex);
        {
                /* See if task for this filename already exists. */
                Task *task;
                HASH_FIND_STR(task_hash, filename, task);
                if (task == NULL) {
                        task = mp_alloc(&mp_tasks);
                        
                        /* Set task filename and add to hash. */
                        assert(*filename != '\0' && strlen(filename) < sizeof(task->filename));
                        strcpy(task->filename, filename);
                        HASH_ADD_STR(task_hash, filename, task);
                        
                        /* Set source buffer and size. */
                        task->img_data = img_data;
                        task->img_size = img_size;
                        
                        if (texture_is_loaded(filename, flags)) {
                                /* Already loaded: add to finished_tasks. */
                                DL_PREPEND(finished_tasks, task);
                                num_finished++;
                        } else {
                                /*
                                 * Insert into active list and signal task
                                 * processing thread.
                                 */
                                task->active = 1;
                                DL_PREPEND(active_tasks, task);
                                SDL_CondSignal(checktask_cond);
                        }
                } else if (task->active) {
                        /* Move to the front of active task queue. */
                        DL_DELETE(active_tasks, task);
                        DL_PREPEND(active_tasks, task);
                }
                
                /* Set/change group, flags, callback and its data pointer. */
                task->group = (group != 0) ? group : (uintptr_t)sync_cb;
                task->sync_cb = sync_cb;
                task->cb_data = cb_data;
                task->flags = flags;                
        }
        SDL_mutexV(storage_mutex);        
}
Esempio n. 22
0
int cache_insert(struct cache_ops *ops,
		 struct cache_entry *ent)
{
	int rc;

	DBT key_record;
	DBT val_record;

	DB *db_bt = (DB *) ops->opaque;

	key_record.data = &ent->key;
	key_record.size = sizeof(struct cache_key);

	val_record.data = ent;
	val_record.size = sizeof(struct cache_entry);

	struct lru_entry *lru_ent 
		= calloc(1, sizeof(struct lru_entry));

	if (!lru_ent) {
		return -1;
	}

	lru_ent->ent = ent;
	ent->lru_ent = lru_ent;

	DL_APPEND(lru_list, lru_ent);

	/* Since insert into the db copies the structure all members
	 * must be filled in before inserting.
	 */

	rc = db_bt->put(db_bt,
			&key_record,
			&val_record,
			R_SETCURSOR);

	if (rc < 0) {
		DL_DELETE(lru_list, lru_ent);
		free(lru_ent);
	}

	if (ent->rc > 0) {
		cached_bytes += ent->rc;
	}

	return rc;
}
Esempio n. 23
0
void profile_rma_nbload_end(int proc, int rid)
{
    if (!profiling_enabled || !(prof_groups & CAFPROF_GET))
        return;
    rma_node_t *rma_node, tmp;

    PROFILE_GET_END(proc, rid);

    /* remove this RMA from the save list */
    tmp.rmaid = rid;
    rma_node = NULL;
    DL_SEARCH(saved_load_rma_list, rma_node, &tmp, rmaid_cmp);
    if (rma_node)
        DL_DELETE(saved_load_rma_list, rma_node);

}
Esempio n. 24
0
/* Deallocate CFG structure.  */
void
free_cfg (struct control_flow_graph* cfg)
{
  basic_block bb = NULL, tmp = NULL;
  if (cfg == NULL)
    return;
  DL_FOREACH_SAFE (CFG_ENTRY_BLOCK (cfg), bb, tmp)
    {
      /* NOTE: These functions don't remove edges themselves.  */
      utarray_free (bb->succs);
      utarray_free (bb->preds);
      free_var_hash (bb->var_hash);
      if (CFG_ENTRY_BLOCK (cfg) != NULL)
	DL_DELETE (CFG_ENTRY_BLOCK (cfg), bb);
      free (bb);
    }
Esempio n. 25
0
/**
 * @brief In case of opDO_WHILE_BEGIN the list entry is deleted
 * @param exp is needed, because DoWhile check at the end with an IF-statement, whether another iteration is necessary. Therefore an IF-op is generated
 */
void addDoWhileEnd (struct symbol *exp)
{
	struct code *c = code_list;
	while (code_list != (c = c->prev))
	{
		if(c->operation == opDO_WHILE_BEGIN)
		{
			if(c->jmpTo == -777)
			{
				DL_DELETE(code_list,c);
				break;
			}
		}
	}
	genQuad(opIF, exp, NULL, NULL, c->counter_id);
}
Esempio n. 26
0
KUSB_EXP BOOL KUSB_API OvlK_Acquire(
    _out KOVL_HANDLE* OverlappedK,
    _in KOVL_POOL_HANDLE PoolHandle)
{
	PKOVL_EL overlappedEL = NULL;
	PKOVL_POOL_HANDLE_INTERNAL handle;
	BOOL isNewFromPool = FALSE;

	ErrorParamAction(!IsHandleValid(OverlappedK), "OverlappedK", return FALSE);
	*OverlappedK = NULL;

	Pub_To_Priv_OvlPoolK(PoolHandle, handle, return FALSE);
	ErrorSetAction(!PoolHandle_Inc_OvlPoolK(handle), ERROR_RESOURCE_NOT_AVAILABLE, return FALSE, "->PoolHandle_Inc_OvlPoolK");

	overlappedEL = handle->ReleasedList;
	ErrorSetAction(!overlappedEL, ERROR_NO_MORE_ITEMS, PoolHandle_Dec_OvlPoolK(handle); return FALSE, "No more overlapped handles");

	DL_DELETE(handle->ReleasedList, overlappedEL);
	if (!overlappedEL->Handle)
	{
		isNewFromPool = TRUE;
		// Get a new OverlappedK handle.
		overlappedEL->Handle = PoolHandle_Acquire_OvlK(Cleanup_OvlK);
		if (!overlappedEL->Handle)
		{
			DL_PREPEND(handle->ReleasedList, overlappedEL);
			ErrorNoSet(!overlappedEL->Handle, Error, "->PoolHandle_Acquire_OvlK");
		}
	}

	overlappedEL->Handle->MasterLink = overlappedEL;
	overlappedEL->Handle->Pool = handle;
	o_Reuse(overlappedEL->Handle);

	*OverlappedK = (KOVL_HANDLE)overlappedEL->Handle;
	if (isNewFromPool) PoolHandle_Live_OvlK(overlappedEL->Handle);

	overlappedEL->Handle->IsAcquired = 1;
	DL_APPEND(handle->AcquiredList, overlappedEL);

	PoolHandle_Dec_OvlPoolK(handle);
	return TRUE;
Error:
	PoolHandle_Dec_OvlPoolK(handle);
	return FALSE;
}
Esempio n. 27
0
/*-----------------------------------------------------------------------------
*   realloc
*----------------------------------------------------------------------------*/
void *m_realloc_( void *memptr, size_t size, char *file, int lineno )
{
    MemBlock *block, *next_block;
    Bool 	  result;

    init_module();

    /* if input is NULL, behave as malloc */
    if ( memptr == NULL )
        return m_malloc_( size, file, lineno );

    /* find the block */
    block = find_block( memptr, file, lineno );
    check( block, "memory realloc (%u bytes) failed at %s:%d", size, file, lineno );

    /* delete from list as realloc may move block */
    next_block = block->next;		/* remember position */
    DL_DELETE(g_mem_blocks, block);

    /* check fences */
    result = check_fences( block );
    check( result, "memory realloc (%u bytes) failed at %s:%d", size, file, lineno );

    /* reallocate and create new end fence */
    block = realloc( block, BLOCK_SIZE( size ) );
    check( block, "memory realloc (%u bytes) failed at %s:%d", size, file, lineno );

    /* update block */
    block->client_size = size;
    block->file        = file;
    block->lineno      = lineno;

    /* fill end fence */
    memset( END_FENCE_PTR( block ), FENCE_SIGN, FENCE_SIZE );

    /* add to list at the same location as before */
    if (next_block == NULL)
        DL_APPEND(g_mem_blocks, block);
    else
        DL_PREPEND_ELEM(g_mem_blocks, next_block, block);

    return CLIENT_PTR( block );

error:
    return NULL;
}
Esempio n. 28
0
void
mongoc_async_cmd_destroy (mongoc_async_cmd_t *acmd)
{
   BSON_ASSERT (acmd);

   DL_DELETE (acmd->async->cmds, acmd);
   acmd->async->ncmds--;

   bson_destroy (&acmd->cmd);

   if (acmd->reply_needs_cleanup) {
      bson_destroy (&acmd->reply);
   }

   _mongoc_array_destroy (&acmd->array);
   _mongoc_buffer_destroy (&acmd->buffer);

   bson_free (acmd);
}
Esempio n. 29
0
KUSB_EXP BOOL KUSB_API OvlK_Release(
    _in KOVL_HANDLE OverlappedK)
{
	PKOVL_HANDLE_INTERNAL overlapped = NULL;
	BOOL success = FALSE;

	Pub_To_Priv_OvlK(OverlappedK, overlapped, return FALSE);
	ErrorParamAction(!PoolHandle_Inc_OvlK(overlapped), "OverlappedK", return FALSE);

	success = overlapped->Pool ? (InterlockedExchange(&overlapped->IsAcquired, 0) != 0) : FALSE;
	ErrorSet(!success, Done, ERROR_ACCESS_DENIED, "OverlappedK is not acquired.");

	DL_DELETE(overlapped->Pool->AcquiredList, overlapped->MasterLink);
	DL_PREPEND(overlapped->Pool->ReleasedList, overlapped->MasterLink);

Done:
	PoolHandle_Dec_OvlK(overlapped);
	return success;
}
Esempio n. 30
0
static jint detachThread(Env* env, jboolean ignoreAttachCount) {
    env->attachCount--;
    if (!ignoreAttachCount && env->attachCount > 0) {
        return JNI_OK;
    }

    if (env->gatewayFrames) {
        rvmAbort("Cannot detach thread when there are non native frames on the call stack");
    }

    // TODO: Release all monitors still held by this thread (should only be monitors acquired from JNI code)

    Thread* thread = env->currentThread;

    if (rvmExceptionOccurred(env)) {
        threadExitUncaughtException(env, thread);
    }

    if (thread->threadObj->group) {
        rvmCallVoidInstanceMethod(env, thread->threadObj->group, removeThreadMethod, thread->threadObj);
        rvmExceptionClear(env);
    }

    // Set threadPtr to null
    rvmAtomicStoreLong(&thread->threadObj->threadPtr, 0);

    // Notify anyone waiting on this thread (using Thread.join())
    rvmLockObject(env, thread->threadObj->lock);
    rvmObjectNotifyAll(env, thread->threadObj->lock);
    rvmUnlockObject(env, thread->threadObj->lock);

    rvmLockThreadsList();
    thread->status = THREAD_ZOMBIE;
    DL_DELETE(threads, thread);
    pthread_cond_broadcast(&threadsChangedCond);
    rvmTearDownSignals(env);
    env->currentThread = NULL;
    pthread_setspecific(tlsEnvKey, NULL);
    rvmUnlockThreadsList();

    return JNI_OK;
}