static ERL_NIF_TERM update_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ks_returner_t *ret; kstat_raw_reader_t save_raw = NULL; ks_handle_t *handle; kid_t id; ks_instance_t *ksi, *ktmp; ks_nvpair_t *nvpair, *ntmp; kstat_t *kp; int count = 0; ret = new_returner(env); if (argc < 1) { return EKSTAT_RETURN(enif_make_badarg(ret->env)); } if (!enif_get_resource(env, argv[0], kstat_handle, (void **)(&handle))) { return EKSTAT_RETURN(enif_make_badarg(ret->env)); } if ((id = kstat_chain_update(handle->ks_ctl)) == 0 && handle->ks_id != -1) { return EKSTAT_RETURN(EKSTAT_ERROR("kstat_chain_update stopped")); } if (id == -1) { return EKSTAT_RETURN(EKSTAT_ERROR("kid not valid")); } /* Free the instances list */ ksi = list_head(&handle->instances_list); while (ksi != NULL) { nvpair = list_head(&ksi->ks_nvlist); while (nvpair != NULL) { ntmp = nvpair; nvpair = list_next(&ksi->ks_nvlist, nvpair); list_remove(&ksi->ks_nvlist, ntmp); if (ntmp->data_type == KSTAT_DATA_STRING) free(ntmp->value.str.addr.ptr); free(ntmp); } ktmp = ksi; ksi = list_next(&handle->instances_list, ksi); list_remove(&handle->instances_list, ktmp); list_destroy(&ktmp->ks_nvlist); free(ktmp); } for (kp = handle->ks_ctl->kc_chain; kp != NULL; kp = kp->ks_next) { /* Don't bother storing the kstat headers */ if (strncmp(kp->ks_name, "kstat_", 6) == 0) { continue; } /* Don't bother storing raw stats we don't understand */ if (kp->ks_type == KSTAT_TYPE_RAW) { save_raw = lookup_raw_kstat_fn(kp->ks_module, kp->ks_name); if (save_raw == NULL) { continue; } } /* * Allocate a new instance and fill in the values * we know so far. */ ksi = (ks_instance_t *)(malloc(sizeof (ks_instance_t))); if (ksi == NULL) { return EKSTAT_RETURN(EKSTAT_ERROR("ks_instance_t malloc")); } list_link_init(&ksi->ks_next); (void) strlcpy(ksi->ks_module, kp->ks_module, KSTAT_STRLEN); (void) strlcpy(ksi->ks_name, kp->ks_name, KSTAT_STRLEN); (void) strlcpy(ksi->ks_class, kp->ks_class, KSTAT_STRLEN); ksi->ks_instance = kp->ks_instance; ksi->ks_snaptime = kp->ks_snaptime; ksi->ks_type = kp->ks_type; list_create(&ksi->ks_nvlist, sizeof (ks_nvpair_t), offsetof(ks_nvpair_t, nv_next)); SAVE_HRTIME_X(ret, ksi, "crtime", kp->ks_crtime); SAVE_HRTIME_X(ret, ksi, "snaptime", kp->ks_snaptime); /* Insert this instance into a sorted list */ ktmp = list_head(&handle->instances_list); while (ktmp != NULL && compare_instances(ksi, ktmp) < 0) { ktmp = list_next(&handle->instances_list, ktmp); } list_insert_before(&handle->instances_list, ktmp, ksi); /* Read the actual statistics */ id = kstat_read(handle->ks_ctl, kp, NULL); if (id == -1) { continue; } switch (kp->ks_type) { case KSTAT_TYPE_RAW: save_raw(ret, kp, ksi); break; case KSTAT_TYPE_NAMED: save_named(ret, kp, ksi); break; case KSTAT_TYPE_INTR: save_intr(ret, kp, ksi); break; case KSTAT_TYPE_IO: save_io(ret, kp, ksi); break; case KSTAT_TYPE_TIMER: save_timer(ret, kp, ksi); break; default: assert(B_FALSE); /* Invalid type */ break; } count++; } return EKSTAT_RETURN(EKSTAT_OK(EKSTAT_INT(count))); }
void socketio_dowork(CONCRETE_IO_HANDLE socket_io) { if (socket_io != NULL) { SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io; if (socket_io_instance->io_state == IO_STATE_OPEN) { int received = 1; LIST_ITEM_HANDLE first_pending_io = list_get_head_item(socket_io_instance->pending_io_list); while (first_pending_io != NULL) { PENDING_SOCKET_IO* pending_socket_io = (PENDING_SOCKET_IO*)list_item_get_value(first_pending_io); if (pending_socket_io == NULL) { socket_io_instance->io_state = IO_STATE_ERROR; indicate_error(socket_io_instance); LogError("Failure: retrieving socket from list"); break; } int send_result = send(socket_io_instance->socket, pending_socket_io->bytes, pending_socket_io->size, 0); if (send_result != pending_socket_io->size) { if (send_result == INVALID_SOCKET) { free(pending_socket_io->bytes); free(pending_socket_io); (void)list_remove(socket_io_instance->pending_io_list, first_pending_io); LogError("Failure: sending Socket information"); socket_io_instance->io_state = IO_STATE_ERROR; indicate_error(socket_io_instance); } else { /* simply wait */ (void)memmove(pending_socket_io->bytes, pending_socket_io->bytes + send_result, pending_socket_io->size - send_result); } } else { if (pending_socket_io->on_send_complete != NULL) { pending_socket_io->on_send_complete(pending_socket_io->callback_context, IO_SEND_OK); } free(pending_socket_io->bytes); free(pending_socket_io); if (list_remove(socket_io_instance->pending_io_list, first_pending_io) != 0) { socket_io_instance->io_state = IO_STATE_ERROR; indicate_error(socket_io_instance); LogError("Failure: unable to remove socket from list"); } } first_pending_io = list_get_head_item(socket_io_instance->pending_io_list); } while (received > 0) { unsigned char* recv_bytes = malloc(RECEIVE_BYTES_VALUE); if (recv_bytes == NULL) { LogError("Socketio_Failure: NULL allocating input buffer."); indicate_error(socket_io_instance); } else { received = recv(socket_io_instance->socket, recv_bytes, RECEIVE_BYTES_VALUE, 0); if (received > 0) { int i; for (i = 0; i < received; i++) { LOG(socket_io_instance->logger_log, 0, "<-%02x ", (unsigned char)recv_bytes[i]); } if (socket_io_instance->on_bytes_received != NULL) { /* explictly ignoring here the result of the callback */ (void)socket_io_instance->on_bytes_received(socket_io_instance->on_bytes_received_context, recv_bytes, received); } } free(recv_bytes); } } } } }
/* Decode the instruction type */ void frm_sm_issue_oldest(struct frm_sm_t *sm, int active_fb) { struct frm_uop_t *uop; struct frm_uop_t *oldest_uop; int list_index; int list_entries; int i; int issued_insts; /* Branch unit */ oldest_uop = NULL; list_index = 0; list_entries = list_count(sm->fetch_buffers[active_fb]); for (issued_insts = 0; issued_insts < frm_gpu_fe_max_inst_issued_per_type; issued_insts++) { for (i = 0; i < list_entries; i++) { uop = list_get(sm->fetch_buffers[active_fb], list_index); assert(uop); /* Only evaluate branch instructions */ if (uop->inst.info->fmt) { list_index++; continue; } /* Skip all uops that have not yet completed * the fetch */ if (asTiming(frm_gpu)->cycle < uop->fetch_ready) { list_index++; continue; } /* Save the oldest uop */ if (!oldest_uop || uop->fetch_ready < oldest_uop->fetch_ready) { oldest_uop = uop; } /* Issue the oldest branch instruction */ if (oldest_uop && list_count(sm->branch_unit. issue_buffer) < frm_gpu_branch_unit_issue_buffer_size) { oldest_uop->issue_ready = asTiming(frm_gpu)->cycle + frm_gpu_fe_issue_latency; list_remove(sm-> fetch_buffers[active_fb], oldest_uop); list_enqueue(sm->branch_unit. issue_buffer, oldest_uop); /* Trace */ frm_trace("si.inst id=%lld cu=%d wf=%d " "uop_id=%lld stg=\"i\"\n", uop->id_in_sm, sm->id, uop->warp->id, uop->id_in_warp); sm->branch_inst_count++; } } } /* SIMD unit */ oldest_uop = NULL; list_index = 0; list_entries = list_count(sm->fetch_buffers[active_fb]); for (issued_insts = 0; issued_insts < frm_gpu_fe_max_inst_issued_per_type; issued_insts++) { for (i = 0; i < list_entries; i++) { uop = list_get(sm->fetch_buffers[active_fb], list_index); assert(uop); /* Only evaluate SIMD instructions */ if (uop->inst.info->fmt != FRM_FMT_FP_FADD && uop->inst.info->fmt != FRM_FMT_INT_IMAD && uop->inst.info->fmt != FRM_FMT_INT_ISCADD && uop->inst.info->fmt != FRM_FMT_MISC_S2R && uop->inst.info->fmt != FRM_FMT_CTRL_EXIT) { list_index++; continue; } /* Skip all uops that have not yet completed * the fetch */ if (asTiming(frm_gpu)->cycle < uop->fetch_ready) { list_index++; continue; } /* Save the oldest uop */ if (!oldest_uop || uop->fetch_ready < oldest_uop->fetch_ready) { oldest_uop = uop; } /* Issue the oldest SIMD instruction */ if (oldest_uop && list_count(sm->simd_units[active_fb]-> issue_buffer) < frm_gpu_simd_issue_buffer_size) { oldest_uop->issue_ready = asTiming(frm_gpu)->cycle + frm_gpu_fe_issue_latency; list_remove(sm-> fetch_buffers[active_fb], oldest_uop); list_enqueue(sm-> simd_units[active_fb]->issue_buffer, oldest_uop); /* Trace */ frm_trace("si.inst id=%lld cu=%d wf=%d " "uop_id=%lld stg=\"i\"\n", uop->id_in_sm, sm->id, uop->warp->id, uop->id_in_warp); uop->warp_inst_queue_entry->ready_next_cycle = 1; sm->simd_inst_count++; } } } /* Vector memory */ oldest_uop = NULL; list_index = 0; list_entries = list_count(sm->fetch_buffers[active_fb]); for (issued_insts = 0; issued_insts < frm_gpu_fe_max_inst_issued_per_type; issued_insts++) { for (i = 0; i < list_entries; i++) { uop = list_get(sm->fetch_buffers[active_fb], list_index); assert(uop); /* Only evaluate memory instructions */ if (uop->inst.info->fmt != FRM_FMT_LDST_LD && uop->inst.info->fmt != FRM_FMT_LDST_ST && uop->inst.info->fmt != FRM_FMT_MOV_MOV) { list_index++; continue; } /* Skip all uops that have not yet completed * the fetch */ if (asTiming(frm_gpu)->cycle < uop->fetch_ready) { list_index++; continue; } /* Save the oldest uop */ if (!oldest_uop || uop->fetch_ready < oldest_uop->fetch_ready) { oldest_uop = uop; } /* Issue the oldest memory instruction */ if (oldest_uop && list_count(sm-> vector_mem_unit.issue_buffer) < frm_gpu_vector_mem_issue_buffer_size) { oldest_uop->issue_ready = asTiming(frm_gpu)->cycle + frm_gpu_fe_issue_latency; list_remove(sm-> fetch_buffers[active_fb], oldest_uop); list_enqueue(sm-> vector_mem_unit.issue_buffer, oldest_uop); /* Trace */ frm_trace("si.inst id=%lld cu=%d wf=%d " "uop_id=%lld stg=\"i\"\n", uop->id_in_sm, sm->id, uop->warp->id, uop->id_in_warp); uop->warp_inst_queue_entry->ready_next_cycle = 1; sm->vector_mem_inst_count++; } } } /* LDS */ oldest_uop = NULL; list_index = 0; list_entries = list_count(sm->fetch_buffers[active_fb]); for (issued_insts = 0; issued_insts < frm_gpu_fe_max_inst_issued_per_type; issued_insts++) { for (i = 0; i < list_entries; i++) { uop = list_get(sm->fetch_buffers[active_fb], list_index); assert(uop); /* Only evaluate LDS instructions */ //if (uop->inst.info->fmt != FRM_FMT_DS) //{ // list_index++; // continue; //} /* Skip all uops that have not yet completed * the fetch */ if (asTiming(frm_gpu)->cycle < uop->fetch_ready) { list_index++; continue; } /* Save the oldest uop */ if (!oldest_uop || uop->fetch_ready < oldest_uop->fetch_ready) { oldest_uop = uop; } /* Issue the oldest LDS instruction */ if (oldest_uop && list_count( sm->lds_unit.issue_buffer) < frm_gpu_lds_issue_buffer_size) { oldest_uop->issue_ready = asTiming(frm_gpu)->cycle + frm_gpu_fe_issue_latency; list_remove(sm-> fetch_buffers[active_fb], oldest_uop); list_enqueue( sm->lds_unit.issue_buffer, oldest_uop); /* Trace */ frm_trace("si.inst id=%lld cu=%d wf=%d " "uop_id=%lld stg=\"i\"\n", uop->id_in_sm, sm->id, uop->warp->id, uop->id_in_warp); uop->warp_inst_queue_entry->ready_next_cycle = 1; sm->lds_inst_count++; } } } /* Update visualization states for all instructions not issued */ list_entries = list_count(sm->fetch_buffers[active_fb]); for (i = 0; i < list_entries; i++) { uop = list_get(sm->fetch_buffers[active_fb], i); assert(uop); /* Skip all uops that have not yet completed the fetch */ if (asTiming(frm_gpu)->cycle < uop->fetch_ready) { continue; } frm_trace("si.inst id=%lld cu=%d wf=%d uop_id=%lld stg=\"s\"\n", uop->id_in_sm, sm->id, uop->warp->id, uop->id_in_warp); } }
void unregister_type(struct driver_type *type) { log_assert(type->refcount == 0); list_remove(&types, type); }
/*---------------------------------------------------------------------------*/ void channel_close(struct channel *c) { list_remove(channel_list, c); }
/* * Simply remove the zvol from to list of zvols. */ static void zvol_remove(zvol_state_t *zv_remove) { ASSERT(MUTEX_HELD(&zvol_state_lock)); list_remove(&zvol_state_list, zv_remove); }
static void zfs_objset_close(zfsvfs_t *zfsvfs) { zfs_delete_t *zd = &zfsvfs->z_delete_head; znode_t *zp, *nextzp; objset_t *os = zfsvfs->z_os; /* * Stop all delete threads. */ (void) zfs_delete_thread_target(zfsvfs, 0); /* * For forced unmount, at this point all vops except zfs_inactive * are erroring EIO. We need to now suspend zfs_inactive threads * while we are freeing dbufs before switching zfs_inactive * to use behaviour without a objset. */ rw_enter(&zfsvfs->z_um_lock, RW_WRITER); /* * Release all delete in progress znodes * They will be processed when the file system remounts. */ mutex_enter(&zd->z_mutex); while (zp = list_head(&zd->z_znodes)) { list_remove(&zd->z_znodes, zp); zp->z_dbuf_held = 0; dmu_buf_rele(zp->z_dbuf, NULL); } mutex_exit(&zd->z_mutex); /* * Release all holds on dbufs * Note, although we have stopped all other vop threads and * zfs_inactive(), the dmu can callback via znode_pageout_func() * which can zfs_znode_free() the znode. * So we lock z_all_znodes; search the list for a held * dbuf; drop the lock (we know zp can't disappear if we hold * a dbuf lock; then regrab the lock and restart. */ mutex_enter(&zfsvfs->z_znodes_lock); for (zp = list_head(&zfsvfs->z_all_znodes); zp; zp = nextzp) { nextzp = list_next(&zfsvfs->z_all_znodes, zp); if (zp->z_dbuf_held) { /* dbufs should only be held when force unmounting */ zp->z_dbuf_held = 0; mutex_exit(&zfsvfs->z_znodes_lock); dmu_buf_rele(zp->z_dbuf, NULL); /* Start again */ mutex_enter(&zfsvfs->z_znodes_lock); nextzp = list_head(&zfsvfs->z_all_znodes); } } mutex_exit(&zfsvfs->z_znodes_lock); /* * Unregister properties. */ if (!dmu_objset_is_snapshot(os)) zfs_unregister_callbacks(zfsvfs); /* * Switch zfs_inactive to behaviour without an objset. * It just tosses cached pages and frees the znode & vnode. * Then re-enable zfs_inactive threads in that new behaviour. */ zfsvfs->z_unmounted2 = B_TRUE; rw_exit(&zfsvfs->z_um_lock); /* re-enable any zfs_inactive threads */ /* * Close the zil. Can't close the zil while zfs_inactive * threads are blocked as zil_close can call zfs_inactive. */ if (zfsvfs->z_log) { zil_close(zfsvfs->z_log); zfsvfs->z_log = NULL; } /* * Evict all dbufs so that cached znodes will be freed */ if (dmu_objset_evict_dbufs(os, 1)) { txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), 0); (void) dmu_objset_evict_dbufs(os, 0); } /* * Finally close the objset */ dmu_objset_close(os); /* * We can now safely destroy the '.zfs' directory node. */ if (zfsvfs->z_ctldir != NULL) zfsctl_destroy(zfsvfs); }
extern int filetxt_jobacct_process_archive(slurmdb_archive_cond_t *arch_cond) { char line[BUFFER_SIZE], *f[EXPIRE_READ_LENGTH], *fptr = NULL, *logfile_name = NULL, *old_logfile_name = NULL, *filein = NULL, *object = NULL; int file_err=0, new_file, i = 0, rc = SLURM_ERROR; expired_rec_t *exp_rec = NULL; expired_rec_t *exp_rec2 = NULL; List keep_list = list_create(_destroy_exp); List exp_list = list_create(_destroy_exp); List other_list = list_create(_destroy_exp); struct stat statbuf; mode_t prot = 0600; uid_t uid; gid_t gid; FILE *expired_logfile = NULL, *new_logfile = NULL; FILE *fd = NULL; int lc=0; int rec_type = -1; ListIterator itr = NULL; ListIterator itr2 = NULL; slurmdb_job_cond_t *job_cond = NULL; /* Figure out our expiration date */ time_t expiry; if (!arch_cond || !arch_cond->job_cond) { error("no job_cond was given for archive"); return SLURM_ERROR; } job_cond = arch_cond->job_cond; if (!arch_cond->archive_script) filein = slurm_get_accounting_storage_loc(); else filein = arch_cond->archive_script; expiry = time(NULL) - job_cond->usage_end; debug("Purging jobs completed prior to %d", (int)expiry); /* Open the current or specified logfile, or quit */ fd = _open_log_file(filein); if (stat(filein, &statbuf)) { perror("stat'ing logfile"); goto finished; } if ((statbuf.st_mode & S_IFLNK) == S_IFLNK) { error("%s is a symbolic link; --expire requires " "a hard-linked file name", filein); goto finished; } if (!(statbuf.st_mode & S_IFREG)) { error("%s is not a regular file; --expire " "only works on accounting log files", filein); goto finished; } prot = statbuf.st_mode & 0777; gid = statbuf.st_gid; uid = statbuf.st_uid; old_logfile_name = _prefix_filename(filein, ".old."); if (stat(old_logfile_name, &statbuf)) { if (errno != ENOENT) { fprintf(stderr,"Error checking for %s: ", old_logfile_name); perror(""); goto finished; } } else { error("Warning! %s exists -- please remove " "or rename it before proceeding", old_logfile_name); goto finished; } /* create our initial buffer */ while (fgets(line, BUFFER_SIZE, fd)) { lc++; fptr = line; /* break the record into NULL- terminated strings */ exp_rec = xmalloc(sizeof(expired_rec_t)); exp_rec->line = xstrdup(line); for (i = 0; i < EXPIRE_READ_LENGTH; i++) { f[i] = fptr; fptr = strstr(fptr, " "); if (fptr == NULL) break; else *fptr++ = 0; } exp_rec->job = atoi(f[F_JOB]); exp_rec->job_submit = atoi(f[F_JOB_SUBMIT]); rec_type = atoi(f[F_RECTYPE]); /* Odd, but complain some other time */ if (rec_type == JOB_TERMINATED) { if (expiry < atoi(f[F_TIMESTAMP])) { list_append(keep_list, exp_rec); continue; } if (job_cond->partition_list && list_count(job_cond->partition_list)) { itr = list_iterator_create( job_cond->partition_list); while((object = list_next(itr))) if (!strcasecmp(f[F_PARTITION], object)) break; list_iterator_destroy(itr); if (!object) continue; /* no match */ } list_append(exp_list, exp_rec); debug2("Selected: %8d %d", exp_rec->job, (int)exp_rec->job_submit); } else { list_append(other_list, exp_rec); } } if (!list_count(exp_list)) { debug3("No job records were purged."); goto finished; } logfile_name = xmalloc(strlen(filein)+sizeof(".expired")); sprintf(logfile_name, "%s.expired", filein); new_file = stat(logfile_name, &statbuf); if ((expired_logfile = fopen(logfile_name, "a"))==NULL) { error("Error while opening %s", logfile_name); perror(""); xfree(logfile_name); goto finished; } if (new_file) { /* By default, the expired file looks like the log */ chmod(logfile_name, prot); if (chown(logfile_name, uid, gid) == -1) error("Couldn't change ownership of %s to %u:%u", logfile_name, uid, gid); } xfree(logfile_name); logfile_name = _prefix_filename(filein, ".new."); if ((new_logfile = fopen(logfile_name, "w"))==NULL) { error("Error while opening %s", logfile_name); perror(""); fclose(expired_logfile); goto finished; } chmod(logfile_name, prot); /* preserve file protection */ if (chown(logfile_name, uid, gid) == -1)/* and ownership */ error("2 Couldn't change ownership of %s to %u:%u", logfile_name, uid, gid); /* Use line buffering to allow us to safely write * to the log file at the same time as slurmctld. */ if (setvbuf(new_logfile, NULL, _IOLBF, 0)) { perror("setvbuf()"); fclose(expired_logfile); goto finished2; } list_sort(exp_list, (ListCmpF) _cmp_jrec); list_sort(keep_list, (ListCmpF) _cmp_jrec); /* if (params->opt_verbose > 2) { */ /* error("--- contents of exp_list ---"); */ /* itr = list_iterator_create(exp_list); */ /* while((exp_rec = list_next(itr))) */ /* error("%d", exp_rec->job); */ /* error("---- end of exp_list ---"); */ /* list_iterator_destroy(itr); */ /* } */ /* write the expired file */ itr = list_iterator_create(exp_list); while((exp_rec = list_next(itr))) { itr2 = list_iterator_create(other_list); while((exp_rec2 = list_next(itr2))) { if ((exp_rec2->job != exp_rec->job) || (exp_rec2->job_submit != exp_rec->job_submit)) continue; if (fputs(exp_rec2->line, expired_logfile)<0) { perror("writing expired_logfile"); list_iterator_destroy(itr2); list_iterator_destroy(itr); fclose(expired_logfile); goto finished2; } list_remove(itr2); _destroy_exp(exp_rec2); } list_iterator_destroy(itr2); if (fputs(exp_rec->line, expired_logfile)<0) { perror("writing expired_logfile"); list_iterator_destroy(itr); fclose(expired_logfile); goto finished2; } } list_iterator_destroy(itr); fclose(expired_logfile); /* write the new log */ itr = list_iterator_create(keep_list); while((exp_rec = list_next(itr))) { itr2 = list_iterator_create(other_list); while((exp_rec2 = list_next(itr2))) { if (exp_rec2->job != exp_rec->job) continue; if (fputs(exp_rec2->line, new_logfile)<0) { perror("writing keep_logfile"); list_iterator_destroy(itr2); list_iterator_destroy(itr); goto finished2; } list_remove(itr2); _destroy_exp(exp_rec2); } list_iterator_destroy(itr2); if (fputs(exp_rec->line, new_logfile)<0) { perror("writing keep_logfile"); list_iterator_destroy(itr); goto finished2; } } list_iterator_destroy(itr); /* write records in other_list to new log */ itr = list_iterator_create(other_list); while((exp_rec = list_next(itr))) { if (fputs(exp_rec->line, new_logfile)<0) { perror("writing keep_logfile"); list_iterator_destroy(itr); goto finished2; } } list_iterator_destroy(itr); if (rename(filein, old_logfile_name)) { perror("renaming logfile to .old."); goto finished2; } if (rename(logfile_name, filein)) { perror("renaming new logfile"); /* undo it? */ if (!rename(old_logfile_name, filein)) error("Please correct the problem " "and try again"); else error("SEVERE ERROR: Current accounting " "log may have been renamed %s;\n" "please rename it to \"%s\" if necessary, " "and try again", old_logfile_name, filein); goto finished2; } fflush(new_logfile); /* Flush the buffers before forking */ fflush(fd); file_err = slurm_reconfigure(); if (file_err) { file_err = 1; error("Error: Attempt to reconfigure SLURM failed."); if (rename(old_logfile_name, filein)) { perror("renaming logfile from .old."); goto finished2; } } if (fseek(fd, 0, SEEK_CUR)) { /* clear EOF */ perror("looking for late-arriving records"); goto finished2; } /* reopen new logfile in append mode, since slurmctld may write it */ if (freopen(filein, "a", new_logfile) == NULL) { perror("reopening new logfile"); goto finished2; } while (fgets(line, BUFFER_SIZE, fd)) { if (fputs(line, new_logfile)<0) { perror("writing final records"); goto finished2; } } rc = SLURM_SUCCESS; printf("%d jobs expired.\n", list_count(exp_list)); finished2: fclose(new_logfile); if (!file_err) { if (unlink(old_logfile_name) == -1) error("Unable to unlink old logfile %s: %m", old_logfile_name); } finished: xfree(filein); fclose(fd); list_destroy(exp_list); list_destroy(keep_list); list_destroy(other_list); xfree(old_logfile_name); xfree(logfile_name); return rc; }
/* Performs a fingerprint check on the group fp */ static nuint_t group_filter(file_group *fp) { lint_t *p = fp->grp_stp; lint_t *i,*j; nuint_t remove_count = 0; nuint_t fp_sz; /* Prevent crashes (should not happen too often) */ if(!fp || fp->grp_stp == NULL) { return 0; } /* The size read in to build a fingerprint */ fp_sz = MD5_FPSIZE_FORM(fp->grp_stp->fsize); /* Clamp it to some maximum (4KB) */ fp_sz = (fp_sz > MD5_FP_MAX_RSZ) ? MD5_FP_MAX_RSZ : fp_sz; /* Calc fingerprints */ /* Note: this is already multithreaded, because large groups get their own thread */ /* No need for additional threading code here */ while(p) { /* see md5.c for explanations */ md5_fingerprint(p, fp_sz); p=p->next; } /* Compare each other */ i = fp->grp_stp; while(i) { /* Useful debugging stuff: */ /* int z = 0; MDPrintArr(i->fp[0]); printf("|#|"); MDPrintArr(i->fp[1]); printf("|#|"); for(; z < BYTE_MIDDLE_SIZE; z++) { printf("%2x",i->bim[z]); } fflush(stdout); */ if(i->filter) { j=i->next; while(j) { if(j->filter) { if(cmp_fingerprints(i,j)) { /* i 'similiar' to j */ j->filter = false; i->filter = false; } } j = j->next; } if(i->filter) { lint_t *tmp = i; fp->len--; fp->size -= i->fsize; i = list_remove(i); /* Update start / end */ if(tmp == fp->grp_stp) { fp->grp_stp = i; } if(tmp == fp->grp_enp) { fp->grp_enp = i; } remove_count++; continue; } else { i=i->next; continue; } } i=i->next; } return remove_count; }
extern int as_mysql_add_clusters(mysql_conn_t *mysql_conn, uint32_t uid, List cluster_list) { ListIterator itr = NULL; int rc = SLURM_SUCCESS; slurmdb_cluster_rec_t *object = NULL; char *cols = NULL, *vals = NULL, *extra = NULL, *query = NULL, *tmp_extra = NULL; time_t now = time(NULL); char *user_name = NULL; int affect_rows = 0; int added = 0; List assoc_list = NULL; slurmdb_association_rec_t *assoc = NULL; if (check_connection(mysql_conn) != SLURM_SUCCESS) return ESLURM_DB_CONNECTION; assoc_list = list_create(slurmdb_destroy_association_rec); user_name = uid_to_string((uid_t) uid); /* Since adding tables make it so you can't roll back, if there is an error there is no way to easily remove entries in the database, so we will create the tables first and then after that works out then add them to the mix. */ itr = list_iterator_create(cluster_list); while ((object = list_next(itr))) { if (!object->name || !object->name[0]) { error("We need a cluster name to add."); rc = SLURM_ERROR; list_remove(itr); continue; } if ((rc = create_cluster_tables(mysql_conn, object->name)) != SLURM_SUCCESS) { xfree(extra); xfree(cols); xfree(vals); added = 0; if (mysql_errno(mysql_conn->db_conn) == ER_WRONG_TABLE_NAME) rc = ESLURM_BAD_NAME; goto end_it; } } /* Now that all the tables were created successfully lets go ahead and add it to the system. */ list_iterator_reset(itr); while ((object = list_next(itr))) { xstrcat(cols, "creation_time, mod_time, acct"); xstrfmtcat(vals, "%ld, %ld, 'root'", now, now); xstrfmtcat(extra, ", mod_time=%ld", now); if (object->root_assoc) setup_association_limits(object->root_assoc, &cols, &vals, &extra, QOS_LEVEL_SET, 1); xstrfmtcat(query, "insert into %s (creation_time, mod_time, " "name, classification) " "values (%ld, %ld, '%s', %u) " "on duplicate key update deleted=0, mod_time=%ld, " "control_host='', control_port=0, " "classification=%u, flags=0", cluster_table, now, now, object->name, object->classification, now, object->classification); if (debug_flags & DEBUG_FLAG_DB_ASSOC) DB_DEBUG(mysql_conn->conn, "query\n%s", query); rc = mysql_db_query(mysql_conn, query); xfree(query); if (rc != SLURM_SUCCESS) { error("Couldn't add cluster %s", object->name); xfree(extra); xfree(cols); xfree(vals); added=0; break; } affect_rows = last_affected_rows(mysql_conn); if (!affect_rows) { debug2("nothing changed %d", affect_rows); xfree(extra); xfree(cols); xfree(vals); continue; } xstrfmtcat(query, "insert into \"%s_%s\" (%s, lft, rgt) " "values (%s, 1, 2) " "on duplicate key update deleted=0, " "id_assoc=LAST_INSERT_ID(id_assoc)%s;", object->name, assoc_table, cols, vals, extra); xfree(cols); xfree(vals); if (debug_flags & DEBUG_FLAG_DB_ASSOC) DB_DEBUG(mysql_conn->conn, "query\n%s", query); rc = mysql_db_query(mysql_conn, query); xfree(query); if (rc != SLURM_SUCCESS) { error("Couldn't add cluster root assoc"); xfree(extra); added=0; break; } /* we always have a ', ' as the first 2 chars */ tmp_extra = slurm_add_slash_to_quotes(extra+2); xstrfmtcat(query, "insert into %s " "(timestamp, action, name, actor, info) " "values (%ld, %u, '%s', '%s', '%s');", txn_table, now, DBD_ADD_CLUSTERS, object->name, user_name, tmp_extra); xfree(tmp_extra); xfree(extra); debug4("%d(%s:%d) query\n%s", mysql_conn->conn, THIS_FILE, __LINE__, query); rc = mysql_db_query(mysql_conn, query); xfree(query); if (rc != SLURM_SUCCESS) { error("Couldn't add txn"); } else { ListIterator check_itr; char *tmp_name; added++; /* add it to the list and sort */ slurm_mutex_lock(&as_mysql_cluster_list_lock); check_itr = list_iterator_create(as_mysql_cluster_list); while ((tmp_name = list_next(check_itr))) { if (!strcmp(tmp_name, object->name)) break; } list_iterator_destroy(check_itr); if (!tmp_name) { list_append(as_mysql_cluster_list, xstrdup(object->name)); list_sort(as_mysql_cluster_list, (ListCmpF)slurm_sort_char_list_asc); } else error("Cluster %s(%s) appears to already be in " "our cache list, not adding.", tmp_name, object->name); slurm_mutex_unlock(&as_mysql_cluster_list_lock); } /* Add user root by default to run from the root * association. This gets popped off so we need to * read it every time here. */ assoc = xmalloc(sizeof(slurmdb_association_rec_t)); slurmdb_init_association_rec(assoc, 0); list_append(assoc_list, assoc); assoc->cluster = xstrdup(object->name); assoc->user = xstrdup("root"); assoc->acct = xstrdup("root"); assoc->is_def = 1; if (as_mysql_add_assocs(mysql_conn, uid, assoc_list) == SLURM_ERROR) { error("Problem adding root user association"); rc = SLURM_ERROR; } } end_it: list_iterator_destroy(itr); xfree(user_name); list_destroy(assoc_list); if (!added) reset_mysql_conn(mysql_conn); return rc; }
extern List as_mysql_get_clusters(mysql_conn_t *mysql_conn, uid_t uid, slurmdb_cluster_cond_t *cluster_cond) { char *query = NULL; char *extra = NULL; char *tmp = NULL; List cluster_list = NULL; ListIterator itr = NULL; int i=0; MYSQL_RES *result = NULL; MYSQL_ROW row; slurmdb_association_cond_t assoc_cond; ListIterator assoc_itr = NULL; slurmdb_cluster_rec_t *cluster = NULL; slurmdb_association_rec_t *assoc = NULL; List assoc_list = NULL; /* if this changes you will need to edit the corresponding enum */ char *cluster_req_inx[] = { "name", "classification", "control_host", "control_port", "rpc_version", "dimensions", "flags", "plugin_id_select", }; enum { CLUSTER_REQ_NAME, CLUSTER_REQ_CLASS, CLUSTER_REQ_CH, CLUSTER_REQ_CP, CLUSTER_REQ_VERSION, CLUSTER_REQ_DIMS, CLUSTER_REQ_FLAGS, CLUSTER_REQ_PI_SELECT, CLUSTER_REQ_COUNT }; if (check_connection(mysql_conn) != SLURM_SUCCESS) return NULL; if (!cluster_cond) { xstrcat(extra, " where deleted=0"); goto empty; } _setup_cluster_cond_limits(cluster_cond, &extra); empty: xfree(tmp); i=0; xstrfmtcat(tmp, "%s", cluster_req_inx[i]); for(i=1; i<CLUSTER_REQ_COUNT; i++) { xstrfmtcat(tmp, ", %s", cluster_req_inx[i]); } query = xstrdup_printf("select %s from %s%s", tmp, cluster_table, extra); xfree(tmp); xfree(extra); if (debug_flags & DEBUG_FLAG_DB_ASSOC) DB_DEBUG(mysql_conn->conn, "query\n%s", query); if (!(result = mysql_db_query_ret( mysql_conn, query, 0))) { xfree(query); return NULL; } xfree(query); cluster_list = list_create(slurmdb_destroy_cluster_rec); memset(&assoc_cond, 0, sizeof(slurmdb_association_cond_t)); if (cluster_cond) { /* I don't think we want the with_usage flag here. * We do need the with_deleted though. */ //assoc_cond.with_usage = cluster_cond->with_usage; assoc_cond.with_deleted = cluster_cond->with_deleted; } assoc_cond.cluster_list = list_create(NULL); while ((row = mysql_fetch_row(result))) { MYSQL_RES *result2 = NULL; MYSQL_ROW row2; cluster = xmalloc(sizeof(slurmdb_cluster_rec_t)); list_append(cluster_list, cluster); cluster->name = xstrdup(row[CLUSTER_REQ_NAME]); list_append(assoc_cond.cluster_list, cluster->name); /* get the usage if requested */ if (cluster_cond && cluster_cond->with_usage) { as_mysql_get_usage( mysql_conn, uid, cluster, DBD_GET_CLUSTER_USAGE, cluster_cond->usage_start, cluster_cond->usage_end); } cluster->classification = slurm_atoul(row[CLUSTER_REQ_CLASS]); cluster->control_host = xstrdup(row[CLUSTER_REQ_CH]); cluster->control_port = slurm_atoul(row[CLUSTER_REQ_CP]); cluster->rpc_version = slurm_atoul(row[CLUSTER_REQ_VERSION]); cluster->dimensions = slurm_atoul(row[CLUSTER_REQ_DIMS]); cluster->flags = slurm_atoul(row[CLUSTER_REQ_FLAGS]); cluster->plugin_id_select = slurm_atoul(row[CLUSTER_REQ_PI_SELECT]); query = xstrdup_printf( "select cpu_count, cluster_nodes from " "\"%s_%s\" where time_end=0 and node_name='' limit 1", cluster->name, event_table); debug4("%d(%s:%d) query\n%s", mysql_conn->conn, THIS_FILE, __LINE__, query); if (!(result2 = mysql_db_query_ret( mysql_conn, query, 0))) { xfree(query); continue; } xfree(query); if ((row2 = mysql_fetch_row(result2))) { cluster->cpu_count = slurm_atoul(row2[0]); if (row2[1] && row2[1][0]) cluster->nodes = xstrdup(row2[1]); } mysql_free_result(result2); } mysql_free_result(result); if (!list_count(assoc_cond.cluster_list)) { list_destroy(assoc_cond.cluster_list); return cluster_list; } assoc_cond.acct_list = list_create(NULL); list_append(assoc_cond.acct_list, "root"); assoc_cond.user_list = list_create(NULL); list_append(assoc_cond.user_list, ""); assoc_list = as_mysql_get_assocs(mysql_conn, uid, &assoc_cond); list_destroy(assoc_cond.cluster_list); list_destroy(assoc_cond.acct_list); list_destroy(assoc_cond.user_list); if (!assoc_list) return cluster_list; itr = list_iterator_create(cluster_list); assoc_itr = list_iterator_create(assoc_list); while ((cluster = list_next(itr))) { while ((assoc = list_next(assoc_itr))) { if (strcmp(assoc->cluster, cluster->name)) continue; if (cluster->root_assoc) { debug("This cluster %s already has " "an association.", cluster->name); continue; } cluster->root_assoc = assoc; list_remove(assoc_itr); } list_iterator_reset(assoc_itr); } list_iterator_destroy(itr); list_iterator_destroy(assoc_itr); if (list_count(assoc_list)) error("I have %d left over associations", list_count(assoc_list)); list_destroy(assoc_list); return cluster_list; }
void *list_shift(struct list *list) { return list_remove(list, list->first); }
void *list_pop(struct list *list) { return list_remove(list, list->last); }
/*---------------------------------------------------------------------------*/ void route_remove(struct route_entry *e) { list_remove(route_table, e); memb_free(&route_mem, e); }
/* worker thread main function */ void *workermain( void *args ) { luaproc *lp; int procstat; /* main worker loop */ while ( TRUE ) { /* wait until instructed to wake up (because there's work to do or because workers must be destroyed) */ pthread_mutex_lock( &mutex_sched ); while (( list_count( &ready_lp_list ) == 0 ) && ( destroyworkers <= 0 )) { pthread_cond_wait( &cond_wakeup_worker, &mutex_sched ); } if ( destroyworkers > 0 ) { /* check whether workers should be destroyed */ destroyworkers--; /* decrease workers to be destroyed count */ workerscount--; /* decrease active workers count */ /* remove worker from workers table */ lua_getglobal( workerls, LUAPROC_SCHED_WORKERS_TABLE ); lua_pushlightuserdata( workerls, (void *)pthread_self( )); lua_pushnil( workerls ); lua_rawset( workerls, -3 ); lua_pop( workerls, 1 ); pthread_cond_signal( &cond_wakeup_worker ); /* wake other workers up */ pthread_mutex_unlock( &mutex_sched ); pthread_exit( NULL ); /* destroy itself */ } /* remove lua process from the ready queue */ lp = list_remove( &ready_lp_list ); pthread_mutex_unlock( &mutex_sched ); /* execute the lua code specified in the lua process struct */ procstat = luaproc_resume( luaproc_get_state( lp ), NULL, luaproc_get_numargs( lp )); /* reset the process argument count */ luaproc_set_numargs( lp, 0 ); /* has the lua process sucessfully finished its execution? */ if ( procstat == 0 ) { luaproc_set_status( lp, LUAPROC_STATUS_FINISHED ); luaproc_recycle_insert( lp ); /* try to recycle finished lua process */ sched_dec_lpcount(); /* decrease active lua process count */ } /* has the lua process yielded? */ else if ( procstat == LUA_YIELD ) { /* yield attempting to send a message */ if ( luaproc_get_status( lp ) == LUAPROC_STATUS_BLOCKED_SEND ) { luaproc_queue_sender( lp ); /* queue lua process on channel */ /* unlock channel */ luaproc_unlock_channel( luaproc_get_channel( lp )); } /* yield attempting to receive a message */ else if ( luaproc_get_status( lp ) == LUAPROC_STATUS_BLOCKED_RECV ) { luaproc_queue_receiver( lp ); /* queue lua process on channel */ /* unlock channel */ luaproc_unlock_channel( luaproc_get_channel( lp )); } /* yield on explicit coroutine.yield call */ else { /* re-insert the job at the end of the ready process queue */ pthread_mutex_lock( &mutex_sched ); list_insert( &ready_lp_list, lp ); pthread_mutex_unlock( &mutex_sched ); } } /* or was there an error executing the lua process? */ else { /* print error message */ fprintf( stderr, "close lua_State (error: %s)\n", luaL_checkstring( luaproc_get_state( lp ), -1 )); lua_close( luaproc_get_state( lp )); /* close lua state */ sched_dec_lpcount(); /* decrease active lua process count */ } } }
/* This the actual main() of rmlint */ void start_processing(lint_t *b) { file_group *fglist = NULL, emptylist; char lintbuf[128]; char suspbuf[128]; nuint_t ii = 0, lint = 0, spelen = 0, rem_counter = 0, suspicious = 0, path_doubles = 0; if(set->namecluster) { find_double_bases(b); error("\n"); } emptylist.len = 1; emptylist.size = 0; /* Split into groups, based by size */ while(b) { lint_t *q = b, *prev = NULL; nuint_t glen = 0, gsize = 0; while(b && q->fsize == b->fsize) { prev = b; if(b->dupflag == false) { b->dupflag = true; } gsize += b->fsize; glen++; b = b->next; } if(glen == 1) { /* This is only a single element */ /* We can remove it without feelind bad */ q = list_remove(q); if(b != NULL) { b = q; } rem_counter++; } else { /* Mark this isle as 'sublist' by setting next/last pointers */ if(b != NULL) { prev->next = NULL; b->last = NULL; } if(q->fsize != 0) { /* Sort by inode (speeds up IO on normal HDs [not SSDs]) */ q = list_sort(q,cmp_nd); /* Add this group to the list array */ fglist = realloc(fglist, (spelen+1) * sizeof(file_group)); fglist[spelen].grp_stp = q; fglist[spelen].grp_enp = prev; fglist[spelen].len = glen; fglist[spelen].size = gsize; /* Remove 'path-doubles' (files pointing to the physically SAME file) - this requires a node sorted list */ if((set->followlinks && get_cpindex() == 1) || get_cpindex() > 1) path_doubles += rm_double_paths(&fglist[spelen]); /* number_of_groups++ */ spelen++; } else /* this is some other sort of lint (indicated by a size of 0) */ { lint_t *ptr; char flag = 42; bool e_file_printed = false; const char * chown_cmd = " chown $(whoami):$(id -gn)"; q = list_sort(q,cmp_nd); emptylist.grp_stp = q; if((set->followlinks && get_cpindex() == 1) || get_cpindex() > 1) rm_double_paths(&emptylist); /* sort by lint_ID (== dupID) */ ptr = emptylist.grp_stp; ptr = list_sort(ptr,cmp_sort_dupID); emptylist.grp_stp = ptr; emptylist.len = 0; while(ptr) { if(flag != ptr->dupflag) { if(set->verbosity > 1) { error(YEL"\n#"NCO); } else { error("\n#"); } /* -- */ if(ptr->dupflag == TYPE_BLNK) { error(" Bad link(s): \n"); } else if(ptr->dupflag == TYPE_OTMP) { error(" Old Tempfile(s): \n"); } else if(ptr->dupflag == TYPE_EDIR) { error(" Empty dir(s): \n"); } else if(ptr->dupflag == TYPE_JNK_DIRNAME) { error(" Junk dirname(s): \n"); } else if(ptr->dupflag == TYPE_JNK_FILENAME) { error(" Junk filename(s): \n"); } else if(ptr->dupflag == TYPE_NBIN) { error(" Non stripped binarie(s): \n"); } else if(ptr->dupflag == TYPE_BADUID) { error(" Bad UID: \n"); } else if(ptr->dupflag == TYPE_BADGID) { error(" Bad GID: \n"); } else if(ptr->fsize == 0 && e_file_printed == false) { error(" Empty file(s): \n"); e_file_printed = true; } flag = ptr->dupflag; } if(set->verbosity > 1) { error(GRE); } if(ptr->dupflag == TYPE_BLNK) { error(" rm"); } else if(ptr->dupflag == TYPE_OTMP) { error(" rm"); } else if(ptr->dupflag == TYPE_EDIR) { error(" rmdir"); } else if(ptr->dupflag == TYPE_JNK_DIRNAME) { error(" ls"); } else if(ptr->dupflag == TYPE_JNK_FILENAME) { error(" ls"); } else if(ptr->dupflag == TYPE_NBIN) { error(" strip --strip-debug"); } else if(ptr->dupflag == TYPE_BADUID) { error(chown_cmd); } else if(ptr->dupflag == TYPE_BADGID) { error(chown_cmd); } else if(ptr->fsize == 0) { error(" rm"); } if(set->verbosity > 1) { error(NCO); } error(" %s\n",ptr->path); if(set->output) { write_to_log(ptr, false,NULL); } emptylist.size += ptr->fsize; ptr = list_remove(ptr); emptylist.len++; } } } } error("\n"); if(set->searchdup == 0) { nuint_t i = 0; /* rmlint was originally supposed to find duplicates only So we have to free list that whould have been used for dup search before dieing */ for(; i < spelen; i++) { list_clear(fglist[i].grp_stp); } if(fglist) { free(fglist); } die(0); } info("\nNow attempting to find duplicates. This may take a while...\n"); info("Now removing files with unique sizes from list..."); info(""YEL"%ld item(s) less"NCO" in list.",rem_counter); if(path_doubles) { info(" (removed "YEL"%ld pathzombie(s)"NCO")", path_doubles); } info(NCO"\nNow removing "GRE"%ld"NCO" empty files / bad links / junk names from list...\n"NCO, emptylist.len); info("Now sorting groups based on their location on the drive..."); /* Now make sure groups are sorted by their location on the disk*/ qsort(fglist, spelen, sizeof(file_group), cmp_grplist_bynodes); info(" done. \nNow doing fingerprints and full checksums.%c\n",set->verbosity > 4 ? '.' : '\n'); db_done = true; error("%s Duplicate(s):",(set->verbosity > 1) ? YEL"#"NCO : "#"); /* Groups are splitted, now give it to the scheduler * The scheduler will do another filterstep, build checkusm * and compare 'em. The result is printed afterwards */ start_scheduler(fglist, spelen); if(get_dupcounter() == 0) { error("\r "); } else { error("\n"); } /* Gather the total size of removeable data */ for(ii=0; ii < spelen; ii++) { if(fglist[ii].grp_stp != NULL) { lint += fglist[ii].size; } } /* now process the ouptput we gonna print */ size_to_human_readable(lint, lintbuf, 127 /* bufsize */); size_to_human_readable(emptylist.size, suspbuf, 127); /* Now announce */ warning("\n"RED"=> "NCO"In total "RED"%llu"NCO" files, whereof "RED"%llu"NCO" are duplicate(s)",get_totalfiles(), get_dupcounter()); suspicious = emptylist.len + dbase_ctr; if(suspicious > 1) { warning(RED"\n=> %llu"NCO" other suspicious items found ["GRE"%s"NCO"]",emptylist.len + dbase_ctr,suspbuf); } warning("\n"); if(!iAbort) { warning(RED"=> "NCO"Totally "GRE" %s "NCO" [%llu Bytes] can be removed.\n", lintbuf, lint); } if((set->mode == 1 || set->mode == 2) && get_dupcounter()) { warning(RED"=> "NCO"Nothing removed yet!\n"); } warning("\n"); if(set->verbosity == 6) { info("Now calculation finished.. now writing end of log...\n"); info(RED"=> "NCO"In total "RED"%llu"NCO" files, whereof "RED"%llu"NCO" are duplicate(s)\n",get_totalfiles(), get_dupcounter()); if(!iAbort) { info(RED"=> "NCO"In total "GRE" %s "NCO" ["BLU"%llu"NCO" Bytes] can be removed without dataloss.\n", lintbuf, lint); } } if(get_logstream() == NULL && set->output) { error(RED"\nERROR: "NCO); fflush(stdout); perror("Unable to write log"); putchar('\n'); } else if(set->output) { warning("A log has been written to "BLU"%s.log"NCO".\n", set->output); warning("A ready to use shellscript to "BLU"%s.sh"NCO".\n", set->output); } /* End of actual program. Now do some finalizing */ if(fglist) { free(fglist); } }
void * list_pop(List * list) { return list_remove(list, list->head->data); }
/*---------------------------------------------------------------------------*/ void rime_sniffer_remove(struct rime_sniffer *s) { list_remove(sniffers, s); }
apr_status_t heap_gc(heap_t *hp, term_t *roots[], int root_sizes[], int nroots) { apr_memnode_t *saved_active; apr_memnode_t *gc_node, *copy_node; int node_size; int i, j; if (hp->gc_last == NULL) // gc never run gc_node = hp->active; else gc_node = hp->gc_last->next; node_size = node_alloc_size(gc_node); // if gc_last node has enough space then use it for // live term copies, otherwise, create a new node // NB: gc_last may point to gc_node if (hp->gc_last != NULL && hp->gc_last != gc_node && node_free_space(hp->gc_last) >= node_size) copy_node = hp->gc_last; else copy_node = apr_allocator_alloc(hp->allocator, node_size); // temporarily make copy_node active; restore later saved_active = hp->active; hp->active = copy_node; hp->hend = heap_htop(hp); // save gc_node reference for seek_alive; // non-NULL gc_spot means gc in progress hp->gc_spot = gc_node; for (i = 0; i < nroots; i++) for (j = 0; j < root_sizes[i]; j++) seek_live(&roots[i][j], saved_active, hp); assert(hp->active == copy_node); // no overflow hp->gc_spot = NULL; // restore active node if (saved_active != gc_node) hp->active = saved_active; // insert copy_node into the ring: // if gc_node is the last node left // if copy_node is non-empty and was just created; // free copy_node if it was just created // and not put on the list if (gc_node->next == gc_node || (node_alloc_size(copy_node) > 0 && copy_node != hp->gc_last)) { list_insert(copy_node, gc_node); hp->gc_last = copy_node; } else if (copy_node != hp->gc_last) { if (hp->active == copy_node) hp->active = gc_node->next; apr_allocator_free(hp->allocator, copy_node); } hp->alloc_size -= node_alloc_size(gc_node); // reclaim memory list_remove(gc_node); gc_node->next = NULL; apr_allocator_free(hp->allocator, gc_node); // after gc is run, anticipated need is zero hp->hend = heap_htop(hp); return APR_SUCCESS; }
static void trim_map_segment_add(trim_map_t *tm, uint64_t start, uint64_t end, uint64_t txg) { avl_index_t where; trim_seg_t tsearch, *ts_before, *ts_after, *ts; boolean_t merge_before, merge_after; hrtime_t time; ASSERT(MUTEX_HELD(&tm->tm_lock)); VERIFY(start < end); time = gethrtime(); tsearch.ts_start = start; tsearch.ts_end = end; ts = avl_find(&tm->tm_queued_frees, &tsearch, &where); if (ts != NULL) { if (start < ts->ts_start) trim_map_segment_add(tm, start, ts->ts_start, txg); if (end > ts->ts_end) trim_map_segment_add(tm, ts->ts_end, end, txg); return; } ts_before = avl_nearest(&tm->tm_queued_frees, where, AVL_BEFORE); ts_after = avl_nearest(&tm->tm_queued_frees, where, AVL_AFTER); merge_before = (ts_before != NULL && ts_before->ts_end == start); merge_after = (ts_after != NULL && ts_after->ts_start == end); if (merge_before && merge_after) { TRIM_MAP_SINC(tm, ts_after->ts_start - ts_before->ts_end); TRIM_MAP_QDEC(tm); avl_remove(&tm->tm_queued_frees, ts_before); list_remove(&tm->tm_head, ts_before); ts_after->ts_start = ts_before->ts_start; ts_after->ts_txg = txg; ts_after->ts_time = time; kmem_free(ts_before, sizeof (*ts_before)); } else if (merge_before) { TRIM_MAP_SINC(tm, end - ts_before->ts_end); ts_before->ts_end = end; ts_before->ts_txg = txg; ts_before->ts_time = time; } else if (merge_after) { TRIM_MAP_SINC(tm, ts_after->ts_start - start); ts_after->ts_start = start; ts_after->ts_txg = txg; ts_after->ts_time = time; } else { TRIM_MAP_SINC(tm, end - start); TRIM_MAP_QINC(tm); ts = kmem_alloc(sizeof (*ts), KM_SLEEP); ts->ts_start = start; ts->ts_end = end; ts->ts_txg = txg; ts->ts_time = time; avl_insert(&tm->tm_queued_frees, ts, where); list_insert_tail(&tm->tm_head, ts); } }
int main(void) { printf("初始化LinkedList及其正反两个方向的迭代器..."); al = list_create(string, LinkedList, NULL); fwd = list_iterator(al, Forward); bwd = list_iterator(al, Reverse); printf("Ok!\n"); printf("TEST1:空列表时的查询\n"); show(); cont(); printf("TEST2: 用append添加一个元素\n"); appends(1); show(); cont(); printf("TEST3: 用remove_at删除一个元素\n"); printf("删除了%zu个元素\n", list_remove_at(al, 0)); show(); cont(); printf("TEST4: 用insert从头部开始连续添加18个元素\n"); inserts(18, 0); show(); int pos = 0; int from = -1; while ((pos = list_search(al, from, Forward, "South Korea", string, 11)) != -1) { printf("正向搜索所有韩国: %d\n", pos); from = pos + 1; } from = -1; while ((pos = list_search(al, from, Reverse, "Brazil", string, 6)) != -1) { printf("反向搜索所有巴西: %d\n", pos); from = pos - 1; } cont(); printf("TEST5: 用remove删除所有Brazil\n"); list_remove(al, "Brazil", string, 6); show(); cont(); printf("TEST6: 用removeall删除所有元素\n"); list_removeall(al); show(); cont(); printf("TEST7: 用push连续添加12个元素后进行递增快速排序\n"); int i, j; for (i = 0; i < 12; i++) { j = rand() % 16; list_push(al, nations[j], string, strlen(nations[j])); } printf("排序前:\n"); type(); printf("排序后:\n"); list_qsort(al, Asc); type(); printf("二分搜索找韩国: %d\n", list_bi_search(al, "South Korea", string, strlen("South Korea"))); printf("二分搜索找中国: %d\n", list_bi_search(al, "中华人民共和国", string, strlen("中华人民共和国"))); cont(); printf("TEST8: 用enqueue连续添加12个元素后进行递减插入排序\n"); for (i = 0; i < 12; i++) { j = rand() % 16; list_enqueue(al, nations[j], string, strlen(nations[j])); } printf("排序前:\n"); type(); printf("排序后:\n"); list_isort(al, Desc); type(); printf("二分搜索找日本: %d\n", list_bi_search(al, "Japan", string, 5)); printf("二分搜索找台湾: %d\n", list_bi_search(al, "中华民国", string, strlen("中华民国"))); printf("反向排列所有元素\n"); list_reverse(al); type(); printf("二分搜索找韩国: %d\n", list_bi_search(al, "South Korea", string, strlen("South Korea"))); printf("二分搜索找中国: %d\n", list_bi_search(al, "中华人民共和国", string, strlen("中华人民共和国"))); printf("二分搜索找日本: %d\n", list_bi_search(al, "Japan", string, 5)); printf("二分搜索找台湾: %d\n", list_bi_search(al, "中华民国", string, strlen("中华民国"))); cont(); printf("TEST9: 用迭代器迭代删除所有元素\n"); Iterator delit = list_iterator(al, Forward); Element ele = NULL; while ((ele = it_next(delit))) { it_remove(delit); printf("删除元素:\"%s\"\n", POINTOF(ele, char)); free(ele); } type(); cont(); printf("TEST10: 模拟堆栈\n"); printf("连续PUSH三次:\n"); j = rand() % 16; list_push(al, nations[j], string, strlen(nations[j])); type(); j = rand() % 16; list_push(al, nations[j], string, strlen(nations[j])); type(); j = rand() % 16; list_push(al, nations[j], string, strlen(nations[j])); type(); printf("用stacktop读取栈顶元素:"); ele = list_stacktop(al); printf(" \"%s\"\n", POINTOF(ele, char)); free(ele); printf("用pop弹空堆栈:\n"); ele = list_pop(al); printf("\"%s\"\n", POINTOF(ele, char)); free(ele); ele = list_pop(al); printf("\"%s\"\n", POINTOF(ele, char)); free(ele); ele = list_pop(al); printf("\"%s\"\n", POINTOF(ele, char)); free(ele); type(); cont(); printf("TEST11: 模拟队列\n"); printf("连续enqueue三次:\n"); j = rand() % 16; list_enqueue(al, nations[j], string, strlen(nations[j])); type(); j = rand() % 16; list_enqueue(al, nations[j], string, strlen(nations[j])); type(); j = rand() % 16; list_enqueue(al, nations[j], string, strlen(nations[j])); type(); printf("用queuehead读取栈顶元素:"); ele = list_queuehead(al); printf(" \"%s\"\n", POINTOF(ele, char)); free(ele); printf("用dequeue全部出队:\n"); ele = list_dequeue(al); printf("\"%s\"\n", POINTOF(ele, char)); free(ele); ele = list_dequeue(al); printf("\"%s\"\n", POINTOF(ele, char)); free(ele); ele = list_dequeue(al); printf("\"%s\"\n", POINTOF(ele, char)); free(ele); type(); cont(); printf("TEST12: 两个列表相加\n"); Container list2 = list_create(string, LinkedList, NULL); appends(9); printf("原列表:\n"); type(); printf("加上一个空列表:\n"); list_plus(al, list2); type(); printf("加上一个有9个元素的列表:\n"); for (i = 0; i < 9; i++) { j = rand() % 16; list_append(list2, nations[j], string, strlen(nations[j])); } list_plus(al, list2); type(); cont(); printf("再减去这个列表:\n"); list_minus(al, list2); type(); printf("再减去一个空列表:\n"); Container empty = list_create(string, LinkedList, NULL); list_minus(al, empty); type(); cont(); printf("添加到18个元素后再进行retain操作,类似取交集\n"); appends(18); printf("原列表:\n"); type(); printf("list2:\n"); for (i = 0; i < 9; i++) { ele = list_get(list2, i); printf("%s, ", POINTOF(ele, char)); free(ele); } printf("\n"); list_retain(al, list2); printf("retain后:\n"); type(); printf("retain一个空列表:\n"); list_retain(al, empty); type(); printf("FIN: 销毁列表和迭代器..."); it_destroy(fwd); it_destroy(bwd); list_destroy(al); list_destroy(list2); list_destroy(empty); printf("Ok!\n"); return 0; }
static bool item_remove(Item **head, Item *w, Mutex *mutex) { return list_remove((pList*) head, (pList) w, pnext_item, mutex); }
/*---------------------------------------------------------------------------*/ void shell_unregister_command(struct shell_command *c) { list_remove(commands, c); }
/*---------------------------------------------------------------------------*/ static nbr_table_key_t * nbr_table_allocate(void) { nbr_table_key_t *key; int least_used_count = 0; nbr_table_key_t *least_used_key = NULL; key = memb_alloc(&neighbor_addr_mem); if(key != NULL) { return key; } else { /* No more space, try to free a neighbor. * The replacement policy is the following: remove neighbor that is: * (1) not locked * (2) used by fewest tables * (3) oldest (the list is ordered by insertion time) * */ /* Get item from first key */ key = list_head(nbr_table_keys); while(key != NULL) { int item_index = index_from_key(key); int locked = locked_map[item_index]; /* Never delete a locked item */ if(!locked) { int used = used_map[item_index]; int used_count = 0; /* Count how many tables are using this item */ while(used != 0) { if((used & 1) == 1) { used_count++; } used >>= 1; } /* Find least used item */ if(least_used_key == NULL || used_count < least_used_count) { least_used_key = key; least_used_count = used_count; if(used_count == 0) { /* We won't find any least used item */ break; } } } key = list_item_next(key); } if(least_used_key == NULL) { /* We haven't found any unlocked item, allocation fails */ return NULL; } else { /* Reuse least used item */ int i; for(i = 0; i<MAX_NUM_TABLES; i++) { if(all_tables[i] != NULL && all_tables[i]->callback != NULL) { /* Call table callback for each table that uses this item */ nbr_table_item_t *removed_item = item_from_key(all_tables[i], least_used_key); if(nbr_get_bit(used_map, all_tables[i], removed_item) == 1) { all_tables[i]->callback(removed_item); } } } /* Empty used map */ used_map[index_from_key(least_used_key)] = 0; /* Remove neighbor from list */ list_remove(nbr_table_keys, least_used_key); /* Return associated key */ return least_used_key; } }
/*---------------------------------------------------------------------------*/ static void send_packet(mac_callback_t sent, void *ptr) { struct rdc_buf_list *q; struct neighbor_queue *n; static uint8_t initialized = 0; static uint16_t seqno; const linkaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); if(!initialized) { initialized = 1; /* Initialize the sequence number to a random value as per 802.15.4. */ seqno = random_rand(); } if(seqno == 0) { /* PACKETBUF_ATTR_MAC_SEQNO cannot be zero, due to a pecuilarity in framer-802154.c. */ seqno++; } packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++); /* Look for the neighbor entry */ n = neighbor_queue_from_addr(addr); if(n == NULL) { /* Allocate a new neighbor entry */ n = memb_alloc(&neighbor_memb); if(n != NULL) { /* Init neighbor entry */ linkaddr_copy(&n->addr, addr); n->transmissions = 0; n->collisions = 0; n->deferrals = 0; /* Init packet list for this neighbor */ LIST_STRUCT_INIT(n, queued_packet_list); /* Add neighbor to the list */ list_add(neighbor_list, n); } } if(n != NULL) { /* Add packet to the neighbor's queue */ q = memb_alloc(&packet_memb); if(q != NULL) { q->ptr = memb_alloc(&metadata_memb); if(q->ptr != NULL) { q->buf = queuebuf_new_from_packetbuf(); if(q->buf != NULL) { struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr; /* Neighbor and packet successfully allocated */ if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) { /* Use default configuration for max transmissions */ metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS; } else { metadata->max_transmissions = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS); } metadata->sent = sent; metadata->cptr = ptr; if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) { list_push(n->queued_packet_list, q); } else { list_add(n->queued_packet_list, q); } /* If q is the first packet in the neighbor's queue, send asap */ if(list_head(n->queued_packet_list) == q) { ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n); } return; } memb_free(&metadata_memb, q->ptr); PRINTF("csma: could not allocate queuebuf, dropping packet\n"); } memb_free(&packet_memb, q); PRINTF("csma: could not allocate queuebuf, dropping packet\n"); } /* The packet allocation failed. Remove and free neighbor entry if empty. */ if(list_length(n->queued_packet_list) == 0) { list_remove(neighbor_list, n); memb_free(&neighbor_memb, n); } PRINTF("csma: could not allocate packet, dropping packet\n"); } else { PRINTF("csma: could not allocate neighbor, dropping packet\n"); } mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1); }
static void tcp_sock_accept(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call) { ipc_call_t answer; int socket_id; int asock_id; socket_core_t *sock_core; tcp_sockdata_t *socket; tcp_sockdata_t *asocket; tcp_error_t trc; tcp_sock_t lsocket; tcp_sock_t fsocket; tcp_conn_t *conn; tcp_conn_t *rconn; tcp_sock_lconn_t *lconn; int rc; log_msg(LVL_DEBUG, "tcp_sock_accept()"); socket_id = SOCKET_GET_SOCKET_ID(call); asock_id = SOCKET_GET_NEW_SOCKET_ID(call); sock_core = socket_cores_find(&client->sockets, socket_id); if (sock_core == NULL) { async_answer_0(callid, ENOTSOCK); return; } socket = (tcp_sockdata_t *)sock_core->specific_data; fibril_mutex_lock(&socket->lock); log_msg(LVL_DEBUG, " - verify socket->conn"); if (socket->conn != NULL) { fibril_mutex_unlock(&socket->lock); async_answer_0(callid, EINVAL); return; } if (list_empty(&socket->ready)) { fibril_mutex_unlock(&socket->lock); async_answer_0(callid, ENOENT); return; } lconn = list_get_instance(list_first(&socket->ready), tcp_sock_lconn_t, ready_list); list_remove(&lconn->ready_list); conn = lconn->conn; tcp_uc_set_cstate_cb(conn, NULL, NULL); /* Replenish listening connection */ lsocket.addr.ipv4 = TCP_IPV4_ANY; lsocket.port = sock_core->port; fsocket.addr.ipv4 = TCP_IPV4_ANY; fsocket.port = TCP_PORT_ANY; trc = tcp_uc_open(&lsocket, &fsocket, ap_passive, tcp_open_nonblock, &rconn); if (rconn == NULL) { /* XXX Clean up */ fibril_mutex_unlock(&socket->lock); async_answer_0(callid, ENOMEM); return; } tcp_uc_set_cstate_cb(rconn, tcp_sock_cstate_cb, lconn); assert(trc == TCP_EOK); rconn->name = (char *)"S"; lconn->conn = rconn; /* Allocate socket for accepted connection */ rc = tcp_sock_create(client, &asocket); if (rc != EOK) { fibril_mutex_unlock(&socket->lock); async_answer_0(callid, rc); return; } asocket->conn = conn; log_msg(LVL_DEBUG, "tcp_sock_accept():create asocket\n"); rc = tcp_sock_finish_setup(asocket, &asock_id); if (rc != EOK) { tcp_sock_uncreate(asocket); fibril_mutex_unlock(&socket->lock); async_answer_0(callid, rc); return; } fibril_add_ready(asocket->recv_fibril); log_msg(LVL_DEBUG, "tcp_sock_accept(): find acore\n"); SOCKET_SET_DATA_FRAGMENT_SIZE(answer, TCP_SOCK_FRAGMENT_SIZE); SOCKET_SET_SOCKET_ID(answer, asock_id); SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(struct sockaddr_in)); async_answer_3(callid, asocket->sock_core->socket_id, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer), IPC_GET_ARG3(answer)); /* Push one fragment notification to client's queue */ log_msg(LVL_DEBUG, "tcp_sock_accept(): notify data\n"); fibril_mutex_unlock(&socket->lock); }
void frm_sm_map_thread_block(struct frm_sm_t *sm, struct frm_thread_block_t *thread_block) { struct frm_grid_t *grid; struct frm_warp_t *warp; int warp_id; int wiq_id; int entry_index; assert(sm->thread_block_count < frm_gpu->thread_blocks_per_sm); assert(!thread_block->id_in_sm); /* Assign thread block ID */ while (thread_block->id_in_sm < frm_gpu->thread_blocks_per_sm && sm->thread_blocks[thread_block->id_in_sm]) thread_block->id_in_sm++; /* Assign thread block to a SM */ sm->thread_blocks[thread_block->id_in_sm] = thread_block; sm->thread_block_count++; /* Remove fully-loaded SM to 'sm_ready' list so that thread blocks * cannot be assigned to it any more */ if (sm->thread_block_count == frm_gpu->thread_blocks_per_sm) list_remove(frm_gpu->sm_ready_list, sm); /* Add SM to 'sm_busy' list if it has not been there */ if (list_index_of(frm_gpu->sm_busy_list, sm) == -1) list_add(frm_gpu->sm_busy_list, sm); /* Set up warps */ for (warp_id = 0; warp_id < thread_block->warp_count; warp_id++) { /* Assign ID */ warp = thread_block->warps[warp_id]; warp->id_in_sm = thread_block->id_in_sm * thread_block->warp_count + warp_id; /* Assign warp instruction queue */ wiq_id = warp->id_in_sm % frm_gpu_num_warp_inst_queues; warp->warp_inst_queue = sm->warp_inst_queues[wiq_id]; /* Assign warp instruction queue entry */ entry_index = warp->id_in_sm / frm_gpu_num_warp_inst_queues; warp->warp_inst_queue_entry = warp->warp_inst_queue->entries[entry_index]; /* Initialize warp instruction queue entry */ warp->warp_inst_queue_entry->valid = 1; warp->warp_inst_queue_entry->ready = 1; warp->warp_inst_queue_entry->warp = warp; } /* Change thread block status to running */ grid = thread_block->grid; list_remove(grid->pending_thread_blocks, thread_block); list_add(grid->running_thread_blocks, thread_block); /* Trace */ frm_trace("frm.map_tb sm=%d tb=%d t_first=%d t_count=%d w_first=%d " "w_count=%d\n", sm->id, thread_block->id, thread_block->threads[0]->id, thread_block->thread_count, thread_block->warps[0]->id, thread_block->warp_count); /* Stats */ sm->mapped_thread_blocks++; if (frm_spatial_report_active) frm_report_mapped_thread_block(sm); }
//////////////////////////////////////////////////////////// // Main DCC connection session thread // void __cdecl GGPROTO::dccmainthread(void*) { uin_t uin; gg_event *e; struct timeval tv; fd_set rd, wd; int ret; SOCKET maxfd; DWORD tick; list_t l; char szFilename[MAX_PATH]; // Zero up lists watches = transfers = requests = l = NULL; debugLogA("dccmainthread(): started. DCC Server Thread Starting"); // Readup number if (!(uin = getDword(GG_KEY_UIN, 0))) { debugLogA("dccmainthread(): No Gadu-Gadu number specified. Exiting."); if (hEvent) SetEvent(hEvent); #ifdef DEBUGMODE debugLogA("dccmainthread(): end 1."); #endif return; } // Create listen socket on config direct port if (!(dcc = gg_dcc_socket_create(uin, (uint16_t)getWord(GG_KEY_DIRECTPORT, GG_KEYDEF_DIRECTPORT)))) { debugLogA("dccmainthread(): Cannot create DCC listen socket. Exiting."); // Signalize mainthread we haven't start if (hEvent) SetEvent(hEvent); #ifdef DEBUGMODE debugLogA("dccmainthread(): end 2."); #endif return; } gg_dcc_port = dcc->port; gg_dcc_ip = inet_addr("255.255.255.255"); debugLogA("dccmainthread(): Listening on port %d.", gg_dcc_port); // Signalize mainthread we started if (hEvent) SetEvent(hEvent); // Add main dcc handler to watches list_add(&watches, dcc, 0); // Do while we are in the main server thread while(pth_dcc.dwThreadId && dcc) { // Timeouts tv.tv_sec = 1; tv.tv_usec = 0; // Prepare descriptiors for select FD_ZERO(&rd); FD_ZERO(&wd); for (maxfd = 0, l = watches; l; l = l->next) { gg_common *w = (gg_common*)l->data; if (!w || w->state == GG_STATE_ERROR || w->state == GG_STATE_IDLE || w->state == GG_STATE_DONE) continue; // Check if it's proper descriptor if (w->fd == -1) continue; if (w->fd > maxfd) maxfd = w->fd; if ((w->check & GG_CHECK_READ)) FD_SET(w->fd, &rd); if ((w->check & GG_CHECK_WRITE)) FD_SET(w->fd, &wd); } // Wait for data on selects ret = select(maxfd + 1, &rd, &wd, NULL, &tv); // Check for select error if (ret == -1) { if (errno == EBADF) debugLogA("dccmainthread(): Bad descriptor on select()."); else if (errno != EINTR) debugLogA("dccmainthread(): Unknown error on select()."); continue; } // Process watches (carefull with l) l = watches; gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); while (l) { struct gg_common *local_c = (gg_common*)l->data; struct gg_dcc *local_dcc = (gg_dcc*)l->data; struct gg_dcc7 *local_dcc7 = (gg_dcc7*)l->data; l = l->next; switch (local_c->type) { default: if (!local_dcc || (!FD_ISSET(local_dcc->fd, &rd) && !FD_ISSET(local_dcc->fd, &wd))) continue; ///////////////////////////////////////////////////////////////// // Process DCC events // Connection broken/closed gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 2, "ft_mutex", 1); if (!(e = gg_dcc_socket_watch_fd(local_dcc))) { debugLogA("dccmainthread(): Socket closed."); // Remove socket and _close gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); list_remove(&watches, local_dcc, 0); gg_dcc_socket_free(local_dcc); // Check if it's main socket if (local_dcc == dcc) dcc = NULL; continue; } else { gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); debugLogA("dccmainthread(): Event: %s", ggdebug_eventtype(e)); } switch(e->type) { // Client connected case GG_EVENT_DCC_NEW: list_add(&watches, e->event.dcc_new, 0); e->event.dcc_new = NULL; break; // case GG_EVENT_NONE: // If transfer in progress do status if (local_dcc->file_fd != -1 && local_dcc->offset > 0 && (((tick = GetTickCount()) - local_dcc->tick) > GGSTATREFRESHEVERY)) { PROTOFILETRANSFERSTATUS pfts; local_dcc->tick = tick; mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc->file_info.filename); memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS)); pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS); pfts.hContact = (UINT_PTR)local_dcc->contact; pfts.flags = (local_dcc->type == GG_SESSION_DCC_SEND); pfts.pszFiles = NULL; pfts.totalFiles = 1; pfts.currentFileNumber = 0; pfts.totalBytes = local_dcc->file_info.size; pfts.totalProgress = local_dcc->offset; pfts.szWorkingDir = local_dcc->folder; pfts.szCurrentFile = szFilename; pfts.currentFileSize = local_dcc->file_info.size; pfts.currentFileProgress = local_dcc->offset; pfts.currentFileTime = 0; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 3, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc, (LPARAM)&pfts); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); } break; // Connection was successfuly ended case GG_EVENT_DCC_DONE: debugLogA("dccmainthread(): Client: %d, Transfer done ! Closing connection.", dcc->peer_uin); // Remove from watches list_remove(&watches, local_dcc, 0); // Close file & success if (local_dcc->file_fd != -1) { PROTOFILETRANSFERSTATUS pfts; mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc->file_info.filename); memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS)); pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS); pfts.hContact = (UINT_PTR)local_dcc->contact; pfts.flags = (local_dcc->type == GG_SESSION_DCC_SEND); pfts.pszFiles = NULL; pfts.totalFiles = 1; pfts.currentFileNumber = 0; pfts.totalBytes = local_dcc->file_info.size; pfts.totalProgress = local_dcc->file_info.size; pfts.szWorkingDir = local_dcc->folder; pfts.szCurrentFile = szFilename; pfts.currentFileSize = local_dcc->file_info.size; pfts.currentFileProgress = local_dcc->file_info.size; pfts.currentFileTime = 0; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 4, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc, (LPARAM)&pfts); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); _close(local_dcc->file_fd); local_dcc->file_fd = -1; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 5, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_SUCCESS, local_dcc, 0); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); } // Free dcc gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL; break; // Client error case GG_EVENT_DCC_ERROR: switch (e->event.dcc_error) { case GG_ERROR_DCC_HANDSHAKE: debugLogA("dccmainthread(): Client: %d, Handshake error.", local_dcc->peer_uin); break; case GG_ERROR_DCC_NET: debugLogA("dccmainthread(): Client: %d, Network error.", local_dcc->peer_uin); break; case GG_ERROR_DCC_FILE: debugLogA("dccmainthread(): Client: %d, File read/write error.", local_dcc->peer_uin); break; case GG_ERROR_DCC_EOF: debugLogA("dccmainthread(): Client: %d, End of file/connection error.", local_dcc->peer_uin); break; case GG_ERROR_DCC_REFUSED: debugLogA("dccmainthread(): Client: %d, Connection refused error.", local_dcc->peer_uin); break; default: debugLogA("dccmainthread(): Client: %d, Unknown error.", local_dcc->peer_uin); } // Don't do anything if it's main socket if (local_dcc == dcc) break; // Remove from watches list_remove(&watches, local_dcc, 0); // Close file & fail if (local_dcc->contact) { _close(local_dcc->file_fd); local_dcc->file_fd = -1; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 6, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_FAILED, local_dcc, 0); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); } // Free dcc gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL; break; // Need file acknowledgement case GG_EVENT_DCC_NEED_FILE_ACK: debugLogA("dccmainthread(): Client: %d, File ack filename \"%s\" size %d.", local_dcc->peer_uin, local_dcc->file_info.filename, local_dcc->file_info.size); // Do not watch for transfer until user accept it list_remove(&watches, local_dcc, 0); // Add to waiting transfers list_add(&transfers, local_dcc, 0); ////////////////////////////////////////////////// // Add file recv request { // Make new ggtransfer struct local_dcc->contact = (void*)getcontact(local_dcc->peer_uin, 0, 0, NULL); TCHAR* filenameT = mir_utf8decodeT((char*)dcc->file_info.filename); PROTORECVFILET pre = {0}; pre.dwFlags = PRFF_TCHAR; pre.fileCount = 1; pre.timestamp = time(NULL); pre.descr.t = filenameT; pre.files.t = &filenameT; pre.lParam = (LPARAM)local_dcc; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 7, "ft_mutex", 1); ProtoChainRecvFile((UINT_PTR)local_dcc->contact, &pre); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); mir_free(filenameT); } break; // Need client accept case GG_EVENT_DCC_CLIENT_ACCEPT: debugLogA("dccmainthread(): Client: %d, Client accept.", local_dcc->peer_uin); // Check if user is on the list and if it is my uin if (getcontact(local_dcc->peer_uin, 0, 0, NULL) && getDword(GG_KEY_UIN, -1) == local_dcc->uin) break; // Kill unauthorized dcc list_remove(&watches, dcc, 0); gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL; break; // Client connected as we wished to (callback) case GG_EVENT_DCC_CALLBACK: { int found = 0; debugLogA("dccmainthread(): Callback from client %d.", local_dcc->peer_uin); // Seek for stored callback request for (l = requests; l; l = l->next) { struct gg_dcc *req = (gg_dcc*)l->data; if (req && req->peer_uin == local_dcc->peer_uin) { gg_dcc_set_type(local_dcc, GG_SESSION_DCC_SEND); found = 1; // Copy data req ===> dcc local_dcc->folder = req->folder; local_dcc->contact = req->contact; local_dcc->file_fd = req->file_fd; memcpy(&local_dcc->file_info, &req->file_info, sizeof(struct gg_file_info)); // Copy data back to dcc ===> req memcpy(req, local_dcc, sizeof(struct gg_dcc)); // Remove request list_remove(&requests, req, 0); // Remove dcc from watches list_remove(&watches, local_dcc, 0); // Add request to watches list_add(&watches, req, 0); // Free old dat gg_free_dcc(local_dcc); debugLogA("dccmainthread(): Found stored request to client %d, filename \"%s\" size %d, folder \"%s\".", req->peer_uin, req->file_info.filename, req->file_info.size, req->folder); break; } } if (!found) { debugLogA("dccmainthread(): Unknown request to client %d.", local_dcc->peer_uin); // Kill unauthorized dcc list_remove(&watches, local_dcc, 0); gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL; } break; } } // Free event gg_free_event(e); break; case GG_SESSION_DCC7_SOCKET: case GG_SESSION_DCC7_GET: case GG_SESSION_DCC7_SEND: case GG_SESSION_DCC7_VOICE: if (!local_dcc7 || (!FD_ISSET(local_dcc7->fd, &rd) && !FD_ISSET(local_dcc7->fd, &wd))) continue; ///////////////////////////////////////////////////////////////// // Process DCC7 events // Connection broken/closed gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 8, "ft_mutex", 1); if (!(e = gg_dcc7_watch_fd(local_dcc7))) { debugLogA("dccmainthread(): Socket closed."); // Remove socket and _close gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); list_remove(&watches, local_dcc7, 0); gg_dcc7_free(local_dcc7); continue; } else { gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); debugLogA("dccmainthread(): Event: %s", ggdebug_eventtype(e)); } switch(e->type) { // case GG_EVENT_NONE: // If transfer in progress do status if (local_dcc7->file_fd != -1 && local_dcc7->offset > 0 && (((tick = GetTickCount()) - local_dcc7->tick) > GGSTATREFRESHEVERY)) { PROTOFILETRANSFERSTATUS pfts; local_dcc7->tick = tick; mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc7->filename); memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS)); pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS); pfts.hContact = (UINT_PTR)local_dcc7->contact; pfts.flags = (local_dcc7->type == GG_SESSION_DCC7_SEND); pfts.pszFiles = NULL; pfts.totalFiles = 1; pfts.currentFileNumber = 0; pfts.totalBytes = local_dcc7->size; pfts.totalProgress = local_dcc7->offset; pfts.szWorkingDir = local_dcc7->folder; pfts.szCurrentFile = szFilename; pfts.currentFileSize = local_dcc7->size; pfts.currentFileProgress = local_dcc7->offset; pfts.currentFileTime = 0; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 9, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc7, (LPARAM)&pfts); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); } break; // Connection was successfuly ended case GG_EVENT_DCC7_DONE: debugLogA("dccmainthread(): Client: %d, Transfer done ! Closing connection.", dcc->peer_uin); // Remove from watches list_remove(&watches, local_dcc7, 0); // Close file & success if (local_dcc7->file_fd != -1) { PROTOFILETRANSFERSTATUS pfts; mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc7->filename); memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS)); pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS); pfts.hContact = (UINT_PTR)local_dcc7->contact; pfts.flags = (local_dcc7->type == GG_SESSION_DCC7_SEND); pfts.pszFiles = NULL; pfts.totalFiles = 1; pfts.currentFileNumber = 0; pfts.totalBytes = local_dcc7->size; pfts.totalProgress = local_dcc7->size; pfts.szWorkingDir = local_dcc7->folder; pfts.szCurrentFile = szFilename; pfts.currentFileSize = local_dcc7->size; pfts.currentFileProgress = local_dcc7->size; pfts.currentFileTime = 0; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 10, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc7, (LPARAM)&pfts); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); _close(local_dcc7->file_fd); local_dcc7->file_fd = -1; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 11, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_SUCCESS, local_dcc7, 0); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); } // Free dcc gg_dcc7_free(local_dcc7); break; // Client error case GG_EVENT_DCC7_ERROR: switch (e->event.dcc7_error) { case GG_ERROR_DCC7_HANDSHAKE: debugLogA("dccmainthread(): Client: %d, Handshake error.", local_dcc7->peer_uin); break; case GG_ERROR_DCC7_NET: debugLogA("dccmainthread(): Client: %d, Network error.", local_dcc7->peer_uin); break; case GG_ERROR_DCC7_FILE: debugLogA("dccmainthread(): Client: %d, File read/write error.", local_dcc7->peer_uin); break; case GG_ERROR_DCC7_EOF: debugLogA("dccmainthread(): Client: %d, End of file/connection error.", local_dcc7->peer_uin); break; case GG_ERROR_DCC7_REFUSED: debugLogA("dccmainthread(): Client: %d, Connection refused error.", local_dcc7->peer_uin); break; case GG_ERROR_DCC7_RELAY: debugLogA("dccmainthread(): Client: %d, Relay connection error.", local_dcc7->peer_uin); break; default: debugLogA("dccmainthread(): Client: %d, Unknown error.", local_dcc7->peer_uin); } // Remove from watches list_remove(&watches, local_dcc7, 0); // Close file & fail if (local_dcc7->file_fd != -1) { _close(local_dcc7->file_fd); local_dcc7->file_fd = -1; } if (local_dcc7->contact) { gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 12, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_FAILED, local_dcc7, 0); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); } // Free dcc gg_dcc7_free(local_dcc7); break; } // Free event gg_free_event(e); break; } } gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 1, "ft_mutex", 1); } // Close all dcc client sockets for (l = watches; l; l = l->next) { struct gg_common *c = (gg_common*)l->data; if (!c) continue; if (c->type == GG_SESSION_DCC7_SOCKET || c->type == GG_SESSION_DCC7_SEND || c->type == GG_SESSION_DCC7_GET) { struct gg_dcc7 *local_dcc7 = (gg_dcc7*)l->data; gg_dcc7_free(local_dcc7); } else { struct gg_dcc *local_dcc = (gg_dcc*)l->data; gg_dcc_socket_free(local_dcc); // Check if it's main socket if (local_dcc == dcc) dcc = NULL; } } // Close all waiting for aknowledgle transfers for (l = transfers; l; l = l->next) { struct gg_common *c = (gg_common*)l->data; if (!c) continue; if (c->type == GG_SESSION_DCC7_SOCKET || c->type == GG_SESSION_DCC7_SEND || c->type == GG_SESSION_DCC7_GET) { struct gg_dcc7 *local_dcc7 = (gg_dcc7*)l->data; gg_dcc7_free(local_dcc7); } else { struct gg_dcc *local_dcc = (gg_dcc*)l->data; gg_dcc_socket_free(local_dcc); } } // Close all waiting dcc requests for (l = requests; l; l = l->next) { struct gg_dcc *local_dcc = (gg_dcc*)l->data; if (local_dcc) gg_free_dcc(local_dcc); } list_destroy(watches, 0); list_destroy(transfers, 0); list_destroy(requests, 0); gg_dcc_port = 0; gg_dcc_ip = 0; debugLogA("dccmainthread(): end. DCC Server Thread Ending"); }
/* Decode the instruction type */ void frm_sm_issue_first(struct frm_sm_t *sm, int active_fb) { struct frm_uop_t *uop; int list_index = 0; int list_entries; int i; int total_insts_issued = 0; //int scalar_insts_issued = 0; //int branch_insts_issued = 0; //int lds_insts_issued = 0; int simd_insts_issued = 0; int mem_insts_issued = 0; list_entries = list_count(sm->fetch_buffers[active_fb]); for (i = 0; i < list_entries; i++) { uop = list_get(sm->fetch_buffers[active_fb], list_index); assert(uop); /* Skip all uops that have not yet completed the fetch */ if (asTiming(frm_gpu)->cycle < uop->fetch_ready) { list_index++; continue; } /* Only issue a fixed number of instructions per cycle */ if (total_insts_issued == frm_gpu_fe_issue_width) { frm_trace("si.inst id=%lld cu=%d wf=%d uop_id=%lld " "stg=\"s\"\n", uop->id_in_sm, sm->id, uop->warp->id, uop->id_in_warp); list_index++; continue; } /* Determine instruction type. This simply decodes the * instruction type, so that it can be issued to the proper * hardware unit. It is not the full decode stage */ switch (uop->inst.info->fmt) { ///* Scalar ALU or Branch */ //case FRM_FMT_SOPP: //{ // /* Branch Unit */ // if (uop->inst.micro_inst.sopp.op > 1 && // uop->inst.micro_inst.sopp.op < 10) // { // /* Stall if max branch instructions // * already issued */ // assert(branch_insts_issued <= // frm_gpu_fe_max_inst_issued_per_type); // if (branch_insts_issued == // frm_gpu_fe_max_inst_issued_per_type) // { // frm_trace("si.inst id=%lld cu=%d wf=%d " // "uop_id=%lld stg=\"s\"\n", // uop->id_in_sm, // sm->id, // uop->warp->id, // uop->id_in_warp); // list_index++; // continue; // } // /* Stall if branch unit issue buffer is full */ // if (list_count(sm-> // branch_unit.issue_buffer) == // frm_gpu_branch_unit_issue_buffer_size) // { // frm_trace("si.inst id=%lld cu=%d wf=%d " // "uop_id=%lld stg=\"s\"\n", // uop->id_in_sm, // sm->id, // uop->warp->id, // uop->id_in_warp); // list_index++; // continue; // } // uop->issue_ready = asTiming(frm_gpu)->cycle + // frm_gpu_fe_issue_latency; // list_remove(sm-> // fetch_buffers[active_fb], uop); // list_enqueue(sm-> // branch_unit.issue_buffer, uop); // branch_insts_issued++; // sm->branch_inst_count++; // } // /* Scalar Unit */ // else // { // /* Stall if max scalar instructions // * already issued */ // assert(scalar_insts_issued <= // frm_gpu_fe_max_inst_issued_per_type); // if (scalar_insts_issued == // frm_gpu_fe_max_inst_issued_per_type) // { // frm_trace("si.inst id=%lld cu=%d wf=%d " // "uop_id=%lld stg=\"s\"\n", // uop->id_in_sm, // sm->id, // uop->warp->id, // uop->id_in_warp); // list_index++; // continue; // } // /* Stall if scalar unit issue buffer is full */ // if (list_count(sm-> // scalar_unit.issue_buffer) == // frm_gpu_scalar_unit_issue_buffer_size) // { // frm_trace("si.inst id=%lld cu=%d wf=%d " // "uop_id=%lld stg=\"s\"\n", // uop->id_in_sm, // sm->id, // uop->warp->id, // uop->id_in_warp); // list_index++; // continue; // } // uop->issue_ready = asTiming(frm_gpu)->cycle + // frm_gpu_fe_issue_latency; // list_remove( // sm-> // fetch_buffers[active_fb], uop); // list_enqueue(sm-> // scalar_unit.issue_buffer, uop); // scalar_insts_issued++; // sm->scalar_alu_inst_count++; // } // break; //} //case FRM_FMT_SOP1: //case FRM_FMT_SOP2: //case FRM_FMT_SOPC: //case FRM_FMT_SOPK: //{ // /* Stall if max scalar instructions already issued */ // assert(scalar_insts_issued <= // frm_gpu_fe_max_inst_issued_per_type); // if (scalar_insts_issued == // frm_gpu_fe_max_inst_issued_per_type) // { // frm_trace("si.inst id=%lld cu=%d wf=%d " // "uop_id=%lld stg=\"s\"\n", // uop->id_in_sm, // sm->id, // uop->warp->id, // uop->id_in_warp); // list_index++; // continue; // } // /* Stall if scalar unit issue buffer is full */ // if (list_count(sm->scalar_unit.issue_buffer) // == frm_gpu_scalar_unit_issue_buffer_size) // { // frm_trace("si.inst id=%lld cu=%d wf=%d " // "uop_id=%lld stg=\"s\"\n", // uop->id_in_sm, // sm->id, // uop->warp->id, // uop->id_in_warp); // list_index++; // continue; // } // uop->issue_ready = asTiming(frm_gpu)->cycle + // frm_gpu_fe_issue_latency; // list_remove(sm->fetch_buffers[active_fb], // uop); // list_enqueue(sm->scalar_unit.issue_buffer, // uop); // scalar_insts_issued++; // sm->scalar_alu_inst_count++; // break; //} ///* Scalar memory */ //case FRM_FMT_SMRD: //{ // /* Stall if max scalar instructions already issued */ // assert(scalar_insts_issued <= // frm_gpu_fe_max_inst_issued_per_type); // if (scalar_insts_issued == // frm_gpu_fe_max_inst_issued_per_type) // { // frm_trace("si.inst id=%lld cu=%d wf=%d " // "uop_id=%lld stg=\"s\"\n", // uop->id_in_sm, // sm->id, // uop->warp->id, // uop->id_in_warp); // list_index++; // continue; // } // /* Stall if scalar unit issue buffer is full */ // if (list_count(sm->scalar_unit.issue_buffer) // == frm_gpu_scalar_unit_issue_buffer_size) // { // frm_trace("si.inst id=%lld cu=%d wf=%d " // "uop_id=%lld stg=\"s\"\n", // uop->id_in_sm, // sm->id, // uop->warp->id, // uop->id_in_warp); // list_index++; // continue; // } // uop->issue_ready = asTiming(frm_gpu)->cycle + // frm_gpu_fe_issue_latency; // list_remove(sm->fetch_buffers[active_fb], // uop); // list_enqueue(sm->scalar_unit.issue_buffer, // uop); // scalar_insts_issued++; // sm->scalar_mem_inst_count++; // break; //} /* Vector ALU */ case FRM_FMT_FP_FADD: case FRM_FMT_INT_IMAD: case FRM_FMT_MOV_MOV: case FRM_FMT_MISC_S2R: case FRM_FMT_CTRL_EXIT: { /* Stall if max SIMD instructions already issued */ assert(simd_insts_issued <= frm_gpu_fe_max_inst_issued_per_type); if (simd_insts_issued == frm_gpu_fe_max_inst_issued_per_type) { frm_trace("si.inst id=%lld cu=%d wf=%d " "uop_id=%lld stg=\"s\"\n", uop->id_in_sm, sm->id, uop->warp->id, uop->id_in_warp); list_index++; continue; } /* Stall if SIMD issue buffer is full */ if (list_count(sm->simd_units[active_fb]-> issue_buffer) == frm_gpu_simd_issue_buffer_size) { frm_trace("si.inst id=%lld cu=%d wf=%d " "uop_id=%lld stg=\"s\"\n", uop->id_in_sm, sm->id, uop->warp->id, uop->id_in_warp); list_index++; continue; } uop->issue_ready = asTiming(frm_gpu)->cycle + frm_gpu_fe_issue_latency; list_remove(sm->fetch_buffers[active_fb], uop); list_enqueue(sm->simd_units[active_fb]-> issue_buffer, uop); uop->warp_inst_queue_entry->ready_next_cycle = 1; simd_insts_issued++; sm->simd_inst_count++; break; } /* Memory instruction */ case FRM_FMT_LDST_LD: case FRM_FMT_LDST_ST: { /* Stall if max vector memory instructions already * issued */ assert(mem_insts_issued <= frm_gpu_fe_max_inst_issued_per_type); if (mem_insts_issued == frm_gpu_fe_max_inst_issued_per_type) { frm_trace("si.inst id=%lld cu=%d wf=%d " "uop_id=%lld stg=\"s\"\n", uop->id_in_sm, sm->id, uop->warp->id, uop->id_in_warp); list_index++; continue; } /* Stall if vector memory issue buffer is full */ if (list_count( sm->vector_mem_unit.issue_buffer) == frm_gpu_vector_mem_issue_buffer_size) { frm_trace("si.inst id=%lld cu=%d wf=%d " "uop_id=%lld stg=\"s\"\n", uop->id_in_sm, sm->id, uop->warp->id, uop->id_in_warp); list_index++; continue; } uop->issue_ready = asTiming(frm_gpu)->cycle + frm_gpu_fe_issue_latency; list_remove(sm->fetch_buffers[active_fb], uop); list_enqueue(sm->vector_mem_unit.issue_buffer, uop); uop->warp_inst_queue_entry->ready_next_cycle = 1; mem_insts_issued++; sm->vector_mem_inst_count++; break; } ///* Local Data Share */ //case FRM_FMT_DS: //{ // /* Stall if max LDS instructions already issued */ // assert(lds_insts_issued <= // frm_gpu_fe_max_inst_issued_per_type); // if (lds_insts_issued == // frm_gpu_fe_max_inst_issued_per_type) // { // frm_trace("si.inst id=%lld cu=%d wf=%d " // "uop_id=%lld stg=\"s\"\n", // uop->id_in_sm, // sm->id, // uop->warp->id, // uop->id_in_warp); // list_index++; // continue; // } // /* Stall if the LDS issue buffer is full */ // if (list_count(sm->lds_unit.issue_buffer) == // frm_gpu_lds_issue_buffer_size) // { // frm_trace("si.inst id=%lld cu=%d wf=%d " // "uop_id=%lld stg=\"s\"\n", // uop->id_in_sm, // sm->id, // uop->warp->id, // uop->id_in_warp); // list_index++; // continue; // } // uop->issue_ready = asTiming(frm_gpu)->cycle + // frm_gpu_fe_issue_latency; // list_remove(sm->fetch_buffers[active_fb], // uop); // list_enqueue(sm->lds_unit.issue_buffer, uop); // uop->warp_inst_queue_entry->ready_next_cycle = 1; // lds_insts_issued++; // sm->lds_inst_count++; // break; //} default: fatal("%s: instruction type not implemented", __FUNCTION__); } total_insts_issued++; /* Trace */ frm_trace("si.inst id=%lld cu=%d wf=%d uop_id=%lld stg=\"i\"\n", uop->id_in_sm, sm->id, uop->warp->id, uop->id_in_warp); } }
/*---------------------------------------------------------------------------*/ static void packet_sent(void *ptr, int status, int num_transmissions) { struct neighbor_queue *n; struct rdc_buf_list *q; struct qbuf_metadata *metadata; clock_time_t time = 0; mac_callback_t sent; void *cptr; int num_tx; int backoff_transmissions; n = ptr; if(n == NULL) { return; } switch(status) { case MAC_TX_OK: case MAC_TX_NOACK: n->transmissions++; break; case MAC_TX_COLLISION: n->collisions++; break; case MAC_TX_DEFERRED: n->deferrals++; break; } for(q = list_head(n->queued_packet_list); q != NULL; q = list_item_next(q)) { if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) == packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) { break; } } if(q != NULL) { metadata = (struct qbuf_metadata *)q->ptr; if(metadata != NULL) { sent = metadata->sent; cptr = metadata->cptr; #if CSMA_ADVANCED num_tx = n->transmissions + n->collisions/8; #else num_tx = n->transmissions; #endif if(status == MAC_TX_COLLISION || status == MAC_TX_NOACK) { /* If the transmission was not performed because of a collision or noack, we must retransmit the packet. */ switch(status) { case MAC_TX_COLLISION: PRINTF("csma: rexmit collision %d\n", n->transmissions); break; case MAC_TX_NOACK: PRINTF("csma: rexmit noack %d\n", n->transmissions); break; case MAC_TX_DEFERRED: PRINTF("phase deferred\n"); break; default: PRINTF("csma: rexmit err %d, %d\n", status, n->transmissions); } #if CSMA_ADVANCED int i; /* The retransmission time must be proportional to the channel check interval of the underlying radio duty cycling layer. */ time = default_timebase() / 3; /* The retransmission time uses a linear backoff so that the interval between the transmissions increase with each retransmit. */ backoff_transmissions = 1; for(i=0; i<num_tx-1; i++) { backoff_transmissions *= 3; } /* Clamp the number of backoffs so that we don't get a too long timeout here, since that will delay all packets in the queue. */ if(backoff_transmissions > 3 * 3) { backoff_transmissions = 3 * 3; } time = default_timebase() + (random_rand() % (backoff_transmissions * time)); if(num_tx < metadata->max_transmissions) { #else /* The retransmission time must be proportional to the channel check interval of the underlying radio duty cycling layer. */ time = default_timebase(); /* The retransmission time uses a linear backoff so that the interval between the transmissions increase with each retransmit. */ backoff_transmissions = n->transmissions + 1; /* Clamp the number of backoffs so that we don't get a too long timeout here, since that will delay all packets in the queue. */ if(backoff_transmissions > 3) { backoff_transmissions = 3; } time = time + (random_rand() % (backoff_transmissions * time)); if(n->transmissions < metadata->max_transmissions) { #endif PRINTF("csma: retransmitting with time %lu %p\n", time, q); ctimer_set(&n->transmit_timer, time, transmit_packet_list, n); /* This is needed to correctly attribute energy that we spent transmitting this packet. */ queuebuf_update_attr_from_packetbuf(q->buf); } else { if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { LOG_FROM_PACKETBUF("csma: drop with status %d after %d transmissions, %d collisions", status, n->transmissions, n->collisions); } free_packet(n, q); mac_call_sent_callback(sent, cptr, status, num_tx); } } else { if(status == MAC_TX_OK) { if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { LOG_FROM_PACKETBUF("csma: rexmit ok after %d transmissions, %d collisions", n->transmissions, n->collisions); } } else { //LOG_FROM_PACKETBUF("csma: rexmit failed %d: %d\n", n->transmissions, status); } free_packet(n, q); mac_call_sent_callback(sent, cptr, status, num_tx); } } } } /*---------------------------------------------------------------------------*/ static void send_packet(mac_callback_t sent, void *ptr) { struct rdc_buf_list *q; struct neighbor_queue *n; static uint16_t seqno; const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); if(seqno == 0) { /* PACKETBUF_ATTR_MAC_SEQNO cannot be zero, due to a pecuilarity in framer-802154.c. */ seqno++; } packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++); /* Look for the neighbor entry */ n = neighbor_queue_from_addr(addr); if(n == NULL) { /* Allocate a new neighbor entry */ n = memb_alloc(&neighbor_memb); if(n != NULL) { /* Init neighbor entry */ rimeaddr_copy(&n->addr, addr); n->transmissions = 0; n->collisions = 0; n->deferrals = 0; /* Init packet list for this neighbor */ LIST_STRUCT_INIT(n, queued_packet_list); /* Add neighbor to the list */ list_add(neighbor_list, n); } } if(n != NULL) { /* Add packet to the neighbor's queue */ q = memb_alloc(&packet_memb); if(q != NULL) { q->ptr = memb_alloc(&metadata_memb); if(q->ptr != NULL) { q->buf = queuebuf_new_from_packetbuf(); if(q->buf != NULL) { struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr; /* Neighbor and packet successfully allocated */ if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) { /* Use default configuration for max transmissions */ metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS; } else { metadata->max_transmissions = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS); } metadata->sent = sent; metadata->cptr = ptr; if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) { list_push(n->queued_packet_list, q); } else { list_add(n->queued_packet_list, q); } /* If q is the first packet in the neighbor's queue, send asap */ if(list_head(n->queued_packet_list) == q) { ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n); } return; } memb_free(&metadata_memb, q->ptr); PRINTF("csma: could not allocate queuebuf, dropping packet\n"); } memb_free(&packet_memb, q); PRINTF("csma: could not allocate queuebuf, dropping packet\n"); } /* The packet allocation failed. Remove and free neighbor entry if empty. */ if(list_length(n->queued_packet_list) == 0) { list_remove(neighbor_list, n); memb_free(&neighbor_memb, n); } PRINTF("csma: could not allocate packet, dropping packet\n"); } else { PRINTF("csma: could not allocate neighbor, dropping packet\n"); } mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1); } /*---------------------------------------------------------------------------*/ static void input_packet(void) { NETSTACK_NETWORK.input(); } /*---------------------------------------------------------------------------*/ static int on(void) { return NETSTACK_RDC.on(); } /*---------------------------------------------------------------------------*/ static int off(int keep_radio_on) { return NETSTACK_RDC.off(keep_radio_on); } /*---------------------------------------------------------------------------*/ static unsigned short channel_check_interval(void) { if(NETSTACK_RDC.channel_check_interval) { return NETSTACK_RDC.channel_check_interval(); } return 0; } /*---------------------------------------------------------------------------*/ static void init(void) { memb_init(&packet_memb); memb_init(&metadata_memb); memb_init(&neighbor_memb); }