void daemon_fork(struct daemon* daemon) { log_assert(daemon); if(!(daemon->views = views_create())) fatal_exit("Could not create views: out of memory"); /* create individual views and their localzone/data trees */ if(!views_apply_cfg(daemon->views, daemon->cfg)) fatal_exit("Could not set up views"); if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->views)) fatal_exit("Could not setup access control list"); /* create global local_zones */ if(!(daemon->local_zones = local_zones_create())) fatal_exit("Could not create local zones: out of memory"); if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg)) fatal_exit("Could not set up local zones"); /* setup modules */ daemon_setup_modules(daemon); /* first create all the worker structures, so we can pass * them to the newly created threads. */ daemon_create_workers(daemon); #if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP) /* in libev the first inited base gets signals */ if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) fatal_exit("Could not initialize main thread"); #endif /* Now create the threads and init the workers. * By the way, this is thread #0 (the main thread). */ daemon_start_others(daemon); /* Special handling for the main thread. This is the thread * that handles signals and remote control. */ #if !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) /* libevent has the last inited base get signals (or any base) */ if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) fatal_exit("Could not initialize main thread"); #endif signal_handling_playback(daemon->workers[0]); /* Start resolver service on main thread. */ log_info("start of service (%s).", PACKAGE_STRING); worker_work(daemon->workers[0]); log_info("service stopped (%s).", PACKAGE_STRING); /* we exited! a signal happened! Stop other threads */ daemon_stop_others(daemon); daemon->need_to_exit = daemon->workers[0]->need_to_exit; }
/** * Function to start one thread. * @param arg: user argument. * @return: void* user return value could be used for thread_join results. */ static void* thread_start(void* arg) { struct worker* worker = (struct worker*)arg; int port_num = 0; log_thread_set(&worker->thread_num); ub_thread_blocksigs(); #ifdef THREADS_DISABLED /* close pipe ends used by main */ tube_close_write(worker->cmd); close_other_pipes(worker->daemon, worker->thread_num); #endif #ifdef SO_REUSEPORT if(worker->daemon->cfg->so_reuseport) port_num = worker->thread_num % worker->daemon->num_ports; else port_num = 0; #endif if(!worker_init(worker, worker->daemon->cfg, worker->daemon->ports[port_num], 0)) fatal_exit("Could not initialize thread"); worker_work(worker); return NULL; }
int edp_init(int thread_num){ int ret = -1; ret = logger_init(); if(ret != 0){ return ret; } // FIXME:pre-alloc memory for your application ret = mcache_init(NULL, 0); if(ret != 0){ log_warn("mcache init fail:%d\n", ret); goto exit_mcache; } ret = hset_init(); if(ret != 0){ log_warn("hset init fail:%d\n", ret); goto exit_hset; } ret = worker_init(thread_num); if(ret != 0){ log_warn("init worker fail:%d\n", ret); goto exit_worker; } ret = emit_init(); if(ret != 0){ log_warn("init emitter fail:%d\n", ret); goto exit_emit; } ret = edpnet_init(); if(ret != 0){ log_warn("init edpnet fail:%d\n", ret); goto exit_net; } log_info("edp have been initialized!\n"); return 0; exit_net: emit_fini(); exit_emit: worker_fini(); exit_worker: hset_fini(); exit_hset: mcache_fini(); exit_mcache: logger_fini(); return ret; }
int main(int argc, char **argv) { int ret; parse_argv(argc, argv); /* seed random number generator */ srandom(time(NULL)); worker_init(); printf("testing single-proposer case...\n"); ret = run_paxos(0); if (ret) { fprintf(stderr, "run_paxos(0) failed with error code %d\n", ret); return EXIT_FAILURE; } printf("testing multi-proposer case...\n"); ret = run_paxos(1); if (ret) { fprintf(stderr, "run_paxos(1) failed with error code %d\n", ret); return EXIT_FAILURE; } return EXIT_SUCCESS; }
server_t* server_init(int port, size_t num_of_workers) { server_t *server = calloc(sizeof(server_t), 1); server_addr_init(&(server->addr), port); server->evbase = event_base_new(); server->evsignal = event_base_new(); server->worker_count = num_of_workers; server->worker_list = calloc(sizeof(worker_t *), server->worker_count); server->worker_thread = calloc(sizeof(pthread_t *), server->worker_count); int i; for(i = 0; i < server->worker_count; i++) { server->worker_list[i] = worker_init(server); server->worker_thread[i] = calloc(sizeof(pthread_t), 1); } server->command_list = command_list_load(); server->msg_buf = msg_buf_init(); server->ketama = Ketama_new(); Ketama_add_server(server->ketama, "127.0.0.1", 6379, 100); Ketama_add_server(server->ketama, "127.0.0.2", 6379, 100); Ketama_add_server(server->ketama, "127.0.0.3", 6379, 100); Ketama_create_continuum(server->ketama); return server; }
static void workers_gen(LmnWorkerGroup *owner, unsigned int worker_num, AutomataRef a, Vector *psyms, BOOL flags) { unsigned int i; owner->workers = LMN_NALLOC(LmnWorker *, worker_num); for (i = 0; i < worker_num; i++) { LmnWorker *w; StateSpaceRef states; if (i == 0) { states = worker_num > 1 ? statespace_make_for_parallel(worker_num, a, psyms) : statespace_make(a, psyms); } else { states = worker_states(workers_get_worker(owner, 0)); } w = lmn_worker_make(states, i, flags); owner->workers[i] = w; w->group = owner; if (owner->do_search) { w->invalid_seeds = vec_make(4); w->cycles = vec_make(4); } /* アルゴリズムの割り当てと初期化 */ worker_set_env(w); worker_init(w); } }
int cmus_init(void) { playable_exts = ip_get_supported_extensions(); cache_init(); worker_init(); play_queue_init(); return 0; }
struct scheduler *scheduler_new(const config_t *cfg) { const int workers = cfg->threads; struct scheduler *s = malloc(sizeof(*s)); if (!s) { dbg_error("could not allocate a scheduler.\n"); return NULL; } size_t r = HPX_CACHELINE_SIZE - sizeof(s->workers[0]) % HPX_CACHELINE_SIZE; size_t padded_size = sizeof(s->workers[0]) + r; size_t total = workers * padded_size; int e = posix_memalign((void**)&s->workers, HPX_CACHELINE_SIZE, total); if (e) { dbg_error("could not allocate a worker array.\n"); scheduler_delete(s); return NULL; } for (int i = 0; i < workers; ++i) { e = worker_init(&s->workers[i], i, i, 64); if (e) { dbg_error("failed to initialize a worker.\n"); scheduler_delete(s); return NULL; } } e = system_barrier_init(&s->barrier, NULL, workers); if (e) { dbg_error("failed to allocate the scheduler barrier.\n"); scheduler_delete(s); return NULL; } // initialize the run state. sync_store(&s->stopped, SCHED_STOP, SYNC_RELEASE); s->run_state.state = SCHED_STOP; s->run_state.lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; s->run_state.running = (pthread_cond_t)PTHREAD_COND_INITIALIZER; sync_store(&s->next_tls_id, 0, SYNC_RELEASE); s->n_workers = workers; s->n_active_workers = workers; s->wf_threshold = cfg->sched_wfthreshold; thread_set_stack_size(cfg->stacksize); log_sched("initialized a new scheduler.\n"); // bind a worker for this thread so that we can spawn lightweight threads _bind_self(&s->workers[0]); log_sched("worker 0 ready.\n"); return s; }
void scrypt_init(scrypt_worker_t *worker, net_config_t *netconf, dfe_context *dfe, uint32_t *dfe_buffer){ memset(worker, 0, sizeof(*worker)); worker_init(worker, netconf); worker->dfe = dfe; worker->dfe_buffer = dfe_buffer; uint32_t nscrypt = dfe_get_num_scrypt(dfe); worker->ostate_buffer = malloc(sizeof(uint32_t)* 8 * nscrypt); worker->tstate_buffer = malloc(sizeof(uint32_t)* 8 * nscrypt); }
int main(void) { long i = 0; worker_pool pool1, pool2; puts("Case 1 : 10 actions (5s) + worker_join"); puts("---------------------------------------"); worker_init(&pool1); for(; i < ACTION_NB; i++) { action_to_do[i].perform = my_action; action_to_do[i].args = (void*) i; worker_add(&pool1, &action_to_do[i]); printf("Action #%li added\n", i); } worker_join(&pool1); puts("All actions terminated"); worker_quit(&pool1); puts("---------------------------------------"); puts("Case 2 : 10 actions (5s) + worker_quit after 1s"); puts("---------------------------------------"); worker_init(&pool2); for(i = 0; i < ACTION_NB; i++) { action_to_do[i].perform = my_action; action_to_do[i].args = (void*) i; worker_add(&pool2, &action_to_do[i]); printf("Action #%li added\n", i); } worker_quit(&pool2); puts("All actions canceled"); puts("---------------------------------------"); return 0; }
void armas_sched_init(armas_scheduler_t *S, int n, int qlen) { int i, last_cpu; S->workers = calloc(n, sizeof(armas_worker_t)); S->nworker = n; last_cpu = -1; for (i = 0; i < n; i++) { worker_init(&S->workers[i], i+1, qlen, S); // pick up next cpu from list available cpus last_cpu = next_cpu_in_set(&S->cpus, last_cpu); S->workers[i].cpuid = last_cpu; } S->nsched = 0; }
void armas_sched_conf(armas_scheduler_t *S, armas_conf_t *conf, int qlen) { int i, last_cpu; S->workers = calloc(conf->maxproc, sizeof(armas_worker_t)); S->nworker = conf->maxproc; last_cpu = -1; for (i = 0; i < conf->maxproc; i++) { worker_init(&S->workers[i], i+1, qlen, S); S->workers[i].cmem = conf->cmem ? conf->cmem : 10240; S->workers[i].l1mem = conf->l1mem ? conf->l1mem : 5120; // pick up next cpu from list available cpus last_cpu = next_cpu_in_set(&S->cpus, last_cpu); S->workers[i].cpuid = last_cpu; } S->nsched = 0; }
/*===========================================================================* * sef_cb_lu_state_changed * *===========================================================================*/ static void sef_cb_lu_state_changed(int old_state, int state) { /* Worker threads (especially their stacks) pose a serious problem for state * transfer during live update, and therefore, we shut down all worker threads * during live update and restart them afterwards. This function is called in * the old VFS instance when the state changed. We use it to restart worker * threads after a failed live update. */ if (state != SEF_LU_STATE_NULL) return; switch (old_state) { case SEF_LU_STATE_REQUEST_FREE: case SEF_LU_STATE_PROTOCOL_FREE: worker_init(); } }
/*===========================================================================* * sef_cb_init_lu * *===========================================================================*/ static int sef_cb_init_lu(int type, sef_init_info_t *info) { /* This function is called in the new VFS instance during a live update. */ int r; /* Perform regular state transfer. */ if ((r = SEF_CB_INIT_LU_DEFAULT(type, info)) != OK) return r; /* Recreate worker threads, if necessary. */ switch (info->prepare_state) { case SEF_LU_STATE_REQUEST_FREE: case SEF_LU_STATE_PROTOCOL_FREE: worker_init(); } return OK; }
int tracker_init(Tracker *t) { int i; for(i=0; i< WORKER_NO; i++) { if(worker_init(&t->workers[i], i) <0 ) { goto error; } } return 0; error: while(i>0) { --i; woker_destory(&t->workers[i]); } return -1; }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info) { /* Initialize the virtual file server. */ int s, i; struct fproc *rfp; message mess; struct rprocpub rprocpub[NR_BOOT_PROCS]; self = NULL; verbose = 0; /* Initialize proc endpoints to NONE */ for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { rfp->fp_endpoint = NONE; rfp->fp_pid = PID_FREE; } /* Initialize the process table with help of the process manager messages. * Expect one message for each system process with its slot number and pid. * When no more processes follow, the magic process number NONE is sent. * Then, stop and synchronize with the PM. */ do { if ((s = sef_receive(PM_PROC_NR, &mess)) != OK) panic("VFS: couldn't receive from PM: %d", s); if (mess.m_type != VFS_PM_INIT) panic("unexpected message from PM: %d", mess.m_type); if (NONE == mess.VFS_PM_ENDPT) break; rfp = &fproc[mess.VFS_PM_SLOT]; rfp->fp_flags = FP_NOFLAGS; rfp->fp_pid = mess.VFS_PM_PID; rfp->fp_endpoint = mess.VFS_PM_ENDPT; rfp->fp_grant = GRANT_INVALID; rfp->fp_blocked_on = FP_BLOCKED_ON_NONE; rfp->fp_realuid = (uid_t) SYS_UID; rfp->fp_effuid = (uid_t) SYS_UID; rfp->fp_realgid = (gid_t) SYS_GID; rfp->fp_effgid = (gid_t) SYS_GID; rfp->fp_umask = ~0; } while (TRUE); /* continue until process NONE */ mess.m_type = OK; /* tell PM that we succeeded */ s = ipc_send(PM_PROC_NR, &mess); /* send synchronization message */ system_hz = sys_hz(); /* Subscribe to block and character driver events. */ s = ds_subscribe("drv\\.[bc]..\\..*", DSF_INITIAL | DSF_OVERWRITE); if (s != OK) panic("VFS: can't subscribe to driver events (%d)", s); /* Initialize worker threads */ worker_init(); /* Initialize global locks */ if (mthread_mutex_init(&bsf_lock, NULL) != 0) panic("VFS: couldn't initialize block special file lock"); init_dmap(); /* Initialize device table. */ /* Map all the services in the boot image. */ if ((s = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0, (vir_bytes) rprocpub, sizeof(rprocpub))) != OK){ panic("sys_safecopyfrom failed: %d", s); } for (i = 0; i < NR_BOOT_PROCS; i++) { if (rprocpub[i].in_use) { if ((s = map_service(&rprocpub[i])) != OK) { panic("VFS: unable to map service: %d", s); } } } /* Initialize locks and initial values for all processes. */ for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { if (mutex_init(&rfp->fp_lock, NULL) != 0) panic("unable to initialize fproc lock"); rfp->fp_worker = NULL; #if LOCK_DEBUG rfp->fp_vp_rdlocks = 0; rfp->fp_vmnt_rdlocks = 0; #endif /* Initialize process directories. mount_fs will set them to the * correct values. */ for (i = 0; i < OPEN_MAX; i++) rfp->fp_filp[i] = NULL; rfp->fp_rd = NULL; rfp->fp_wd = NULL; } init_vnodes(); /* init vnodes */ init_vmnts(); /* init vmnt structures */ init_select(); /* init select() structures */ init_filps(); /* Init filp structures */ /* Mount PFS and initial file system root. */ worker_start(fproc_addr(VFS_PROC_NR), do_init_root, &mess /*unused*/, FALSE /*use_spare*/); return(OK); }
int main(void) { worker_init(); worker_event_loop(); worker_deinit(); }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info) { /* Initialize the virtual file server. */ int s, i; struct fproc *rfp; message mess; struct rprocpub rprocpub[NR_BOOT_PROCS]; force_sync = 0; receive_from = ANY; self = NULL; verbose = 0; /* Initialize proc endpoints to NONE */ for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { rfp->fp_endpoint = NONE; rfp->fp_pid = PID_FREE; } /* Initialize the process table with help of the process manager messages. * Expect one message for each system process with its slot number and pid. * When no more processes follow, the magic process number NONE is sent. * Then, stop and synchronize with the PM. */ do { if ((s = sef_receive(PM_PROC_NR, &mess)) != OK) panic("VFS: couldn't receive from PM: %d", s); if (mess.m_type != PM_INIT) panic("unexpected message from PM: %d", mess.m_type); if (NONE == mess.PM_PROC) break; rfp = &fproc[mess.PM_SLOT]; rfp->fp_flags = FP_NOFLAGS; rfp->fp_pid = mess.PM_PID; rfp->fp_endpoint = mess.PM_PROC; rfp->fp_grant = GRANT_INVALID; rfp->fp_blocked_on = FP_BLOCKED_ON_NONE; rfp->fp_realuid = (uid_t) SYS_UID; rfp->fp_effuid = (uid_t) SYS_UID; rfp->fp_realgid = (gid_t) SYS_GID; rfp->fp_effgid = (gid_t) SYS_GID; rfp->fp_umask = ~0; } while (TRUE); /* continue until process NONE */ mess.m_type = OK; /* tell PM that we succeeded */ s = send(PM_PROC_NR, &mess); /* send synchronization message */ /* All process table entries have been set. Continue with initialization. */ fp = &fproc[_ENDPOINT_P(VFS_PROC_NR)];/* During init all communication with * FSes is on behalf of myself */ init_dmap(); /* Initialize device table. */ system_hz = sys_hz(); /* Map all the services in the boot image. */ if ((s = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0, (vir_bytes) rprocpub, sizeof(rprocpub), S)) != OK){ panic("sys_safecopyfrom failed: %d", s); } for (i = 0; i < NR_BOOT_PROCS; i++) { if (rprocpub[i].in_use) { if ((s = map_service(&rprocpub[i])) != OK) { panic("VFS: unable to map service: %d", s); } } } /* Subscribe to block and character driver events. */ s = ds_subscribe("drv\\.[bc]..\\..*", DSF_INITIAL | DSF_OVERWRITE); if (s != OK) panic("VFS: can't subscribe to driver events (%d)", s); /* Initialize worker threads */ for (i = 0; i < NR_WTHREADS; i++) { worker_init(&workers[i]); } worker_init(&sys_worker); /* exclusive system worker thread */ worker_init(&dl_worker); /* exclusive worker thread to resolve deadlocks */ /* Initialize global locks */ if (mthread_mutex_init(&pm_lock, NULL) != 0) panic("VFS: couldn't initialize pm lock mutex"); if (mthread_mutex_init(&exec_lock, NULL) != 0) panic("VFS: couldn't initialize exec lock"); if (mthread_mutex_init(&bsf_lock, NULL) != 0) panic("VFS: couldn't initialize block special file lock"); /* Initialize event resources for boot procs and locks for all procs */ for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { if (mutex_init(&rfp->fp_lock, NULL) != 0) panic("unable to initialize fproc lock"); #if LOCK_DEBUG rfp->fp_vp_rdlocks = 0; rfp->fp_vmnt_rdlocks = 0; #endif } init_vnodes(); /* init vnodes */ init_vmnts(); /* init vmnt structures */ init_select(); /* init select() structures */ init_filps(); /* Init filp structures */ mount_pfs(); /* mount Pipe File Server */ worker_start(do_init_root); /* mount initial ramdisk as file system root */ yield(); /* force do_init_root to start */ self = NULL; return(OK); }
void workers_init (workers_t ** workers, ozookeeper_t * ozookeeper) { int result; char path[1000]; char octopus[1000]; char comp_name[1000]; oconfig_octopus (ozookeeper->config, octopus); oconfig_comp_name (ozookeeper->config, comp_name); sprintf (path, "/%s/computers/%s/worker_nodes", octopus, comp_name); struct String_vector worker_children; result = zoo_get_children (ozookeeper->zh, path, 0, &worker_children); if (ZOK == result) { //mallocing *workers = malloc (sizeof (workers_t)); (*workers)->size = worker_children.count; (*workers)->id = malloc (sizeof (char *) * (worker_children.count)); (*workers)->pthread = malloc (sizeof (pthread_t) * worker_children.count); //create the threads //localdb object //used to save the counter used to create new vertices localdb_t *localdb; localdb_init (&localdb); int iter; if (worker_children.count < 1000) { worker_t *worker; for (iter = 0; iter < worker_children.count; iter++) { (*workers)->id[iter] = malloc (strlen (worker_children.data[iter]) + 1 + 1 + strlen (comp_name)); sprintf ((*workers)->id[iter], "%s/%s", comp_name, worker_children.data[iter]); worker_init (&worker, ozookeeper->zh, ozookeeper->config, comp_name, worker_children.data[iter] , localdb); pthread_create (&((*workers)->pthread[iter]), NULL, worker_fn, worker); } } else { fprintf (stderr, "\n More workers than allowed.. error exiting"); exit (1); } if (ZOK != result && ZNONODE != result) { fprintf (stderr, "\n Couldnt get the children.. error exiting"); exit (1); } deallocate_String_vector (&worker_children); } }
int main(int len,char** args) { /* char p[80]; */ int i=0; char ch[80]; pxy_worker_t *w; if(pxy_init_master() < 0){ D("master initialize failed"); return -1; } D("master initialized"); /*spawn worker*/ for(;i<config->worker_count;i++){ w = (pxy_worker_t*)(master->workers + i); if(socketpair(AF_UNIX,SOCK_STREAM,0,w->socket_pair) < 0) { D("create socket pair error"); continue; } if(setnonblocking(w->socket_pair[0]) < 0) { D("setnonblocking error fd:#%d",w->socket_pair[0]); continue; } if(setnonblocking(w->socket_pair[1]) < 0) { D("setnonblocking error fd:#%d",w->socket_pair[1]); continue; } pid_t p = fork(); if(p < 0) { D("%s","forkerror"); } else if(p == 0){/*child*/ if(worker_init()<0){ D("worker #%d initialized failed" , getpid()); return -1; } D("worker #%d initialized success", getpid()); close (w->socket_pair[0]); /*child should close the pair[0]*/ ev_file_item_t *f = ev_file_item_new(w->socket_pair[1], worker, worker_recv_cmd, NULL, EV_READABLE | EPOLLET); if(!f){ D("new file item error"); return -1; } if(ev_add_file_item(worker->ev,f) < 0) { D("add event error"); return -1; } if(!worker_start()) { D("worker #%d started failed", getpid()); return -1; } } else{ /*parent*/ w->pid = p; close(w->socket_pair[1]); /*parent close the pair[1]*/ } } while(scanf("%s",ch) >= 0 && strcmp(ch,"quit") !=0){ } w = (pxy_worker_t*)master->workers; pxy_send_command(w,PXY_CMD_QUIT,-1); sleep(5); pxy_master_close(); return 1; }
int main(int argc, char** argv) { int N /* Number of workers */, L /* Number of locks */, T /* Timeout */, i, shm_id /* Shared memory segment id */, lifesign_fds[2] /* Driver life sign */, status /* Worker exit status */; struct timeval timeval; struct rusage rusage /* Worker resource usage */; char *end; pid_t pid; pid_t worker_pid[WORKERS_MAX] /* Worker pid */; int worker_lock[WORKERS_MAX] /* Worker to lock mapping */; long long total_cycles = 0 /* Total number of cycles */; double max_wall = 0.0 /* Maximum wall time */; double total_user = 0.0 /* Total user time */; double total_sys = 0.0 /* Total system time */; /* Initialize variables */ for(i=0; i < WORKERS_MAX; ++i) { worker_pid[i] = 0; worker_lock[i] = 0; } /* Parser arguments */ if (argc < 4) usage(NULL); count_per_cycle = strtol(argv[1], &end, 10); if ((*end != '\0') || (count_per_cycle <= 0) || (errno == ERANGE)) usage("counter increments per cycle '%s' invalid", argv[1]); N = strtol(argv[2], &end, 10); if ((*end != '\0') || (N <= 0) || (errno == ERANGE)) usage("worker count '%s' invalid", argv[2]); if (N > WORKERS_MAX) die(0, "too many workers"); T = strtol(argv[3], &end, 10); if ((*end != '\0') || (T <= 0) || (errno == ERANGE)) usage("timeout '%s' invalid", argv[3]); for(i=4; i < argc; ++i) { int w, l; w = strtol(argv[i], &end, 10); if ((*end != ':') || (w < 0) || (errno == ERANGE)) usage("worker invalid in worker to lock assignment '%s'", argv[i]); if (w >= N) { printf("Ignoring lock assignment '%s' for non-existing worker %d\n", argv[i], w); continue; } l = strtol(end+1, &end, 10); if ((*end != '\0') || (l < 0) || (errno == ERANGE)) usage("lock invalid in worker to lock assignment '%s'", argv[i]); worker_lock[w] = l; } /* Compute necessary number of locks */ L = 0; for(i=0; i < N; ++i) { if (L < worker_lock[i] + 1) L = worker_lock[i] + 1; } /* Create driver life sign. * Once all copies of the pipe's writing end are closed, the process * groups get sent a SIGIO. Since we close the writing end in all * workers, and register a handler for SIGIO with sends a SIGTERM, * this effectively causes the workers to be killed if the driver exits */ if (signal(SIGIO, sighandler_exit) != 0) die(errno, "failed to register life sign signal handler"); if (pipe(lifesign_fds) != 0) die(errno, "failed to create pipe to use as driver life sign"); if ((i = fcntl(lifesign_fds[0], F_GETFL)) < 0) die(errno, "failed to get flags of the driver life sign pipe's watching end"); i |= FNONBLOCK | FASYNC; if (fcntl(lifesign_fds[0], F_SETFL, i) != 0) die(errno, "failed to set flags of the driver life sign pipe's watching end"); if (fcntl(lifesign_fds[0], F_SETOWN, -getpgrp()) != 0) die(errno, "failed to notification pid of the driver life sign pipe's watching end"); /* Create and attach shared memory segment */ if ((shm_id = shmget(IPC_PRIVATE, SHM_SIZE, 0600)) < 0) die(errno, "failed to create shared memory segment"); shm_base = (char*)shmat(shm_id, NULL, 0); if (shm_base == (char*)-1) die(errno, "failed to attach shared memory segment"); if (shmctl(shm_id, IPC_RMID, NULL) != 0) die(errno, "failed to mark shared memory segment for destruction at exit"); shm_next = shm_base; /* Allocate shared memory slices to all shared structured. * All structured are aligned on cache line boundaries. */ shm_worker_wall = (double*) shm_alloc(sizeof(double) * N, sizeof(double)); shm_worker_user = (double*) shm_alloc(sizeof(double) * N, sizeof(double)); shm_worker_sys = (double*) shm_alloc(sizeof(double) * N, sizeof(double)); shm_worker_counter = (counter_t*) shm_alloc(sizeof(counter_t) * N, -1); shm_lock_refs = (lock_ref_t) shm_alloc(sizeof(lock_t) * L, -1); /* Initialize shared memory */ for(i=0; i < N; ++i) { shm_worker_wall[i] = 0.0; shm_worker_user[i] = 0.0; shm_worker_sys[i] = 0.0; shm_worker_counter[i].value = 0; } locks_init(L, N); for(i=0; i < L; ++i) lock_init(shm_lock_refs + i); /* Print configuration */ printf("Cache line size in bytes: %d\n", CACHELINE_SIZE); printf("Counter size in bytes: %d\n", (int)sizeof(counter_t)); printf("Lock size in bytes: %d\n", lock_size()); printf("--\n"); printf("Number of workers: %d\n", N); printf("Number of locks: %d\n", L); /* Launch workers */ for(i=0; i < N; ++i) { pid = fork(); if (pid < 0) die(errno, "failed to fork()"); if (pid == 0) { /* Worker */ volatile counter_t *counter = &shm_worker_counter[i]; lock_ref_t lock = &shm_lock_refs[worker_lock[i]]; /* Global variable, require for sighandler_alarm */ worker_index = i; /* Close owning end of driver life sign pipe */ close(lifesign_fds[1]); /* Initialize locking infrastructure for worker */ worker_init(worker_index); /* Output *before* waiting */ printf("Worker %d uses counter at %p, lock %d at %p\n", i, counter, worker_lock[i], lock_addr(lock)); /* Arrage for elapsed time and resource usage measurement * on worker exit */ if (signal(SIGALRM, sighandler_alarm) != 0) die(errno, "failed to register alarm signal handler"); /* Wait for driver to tell us to start */ kill(getpid(), SIGSTOP); /* Initial time and resource usage measurement. */ if (gettimeofday(&timeval, NULL) != 0) die(errno, "failed to query wall time in worker after launch"); shm_worker_wall[i] -= (double)(timeval.tv_sec) + (double)(timeval.tv_usec)*1e-6; if (getrusage(RUSAGE_SELF, &rusage) != 0) die(errno, "failed to query worker resource usage after launch"); shm_worker_user[i] -= (double)(rusage.ru_utime.tv_sec) + (double)(rusage.ru_utime.tv_usec)*1e-6; shm_worker_sys[i] -= (double)(rusage.ru_stime.tv_sec) + (double)(rusage.ru_stime.tv_usec)*1e-6; child(counter, lock); exit(1); } else { /* Driver */ worker_pid[i] = pid; } } /* Wait for workers to finish launching */ for(i=0; i < N; ++i) { if ((wait4(worker_pid[i], &status, WUNTRACED, NULL) < 0) || !WIFSTOPPED(status) ) { die(0, "worker %d with pid %d failed", i, worker_pid[i]); } } /* Tell workers to start */ printf("Starting workers\n"); kill(-getpgrp(), SIGCONT); /* Let workers run for a while */ sleep(T); /* Terminate workers */ for(i=0; i < N; ++i) kill(worker_pid[i], SIGALRM); /* Aggregate data * Must wait for worker to exit before reading its stats */ for(i=0; i < N; ++i) { if ((wait4(worker_pid[i], &status, WUNTRACED, NULL) < 0) || !WIFEXITED(status) || (WEXITSTATUS(status) != 0) ) { die(0, "worker %d with pid %d failed (%s %d)", i, worker_pid[i], WIFEXITED(status) ? "exitcode" : "signal", WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status) ); } total_cycles += shm_worker_counter[i].value / count_per_cycle; if (max_wall < shm_worker_wall[i]) max_wall = shm_worker_wall[i]; total_user += shm_worker_user[i]; total_sys += shm_worker_sys[i]; } /* Show data */ for(i=0; i < N; ++i) { printf(" Worker %d cycles: %llu\n", i, shm_worker_counter[i].value / count_per_cycle); printf(" Worker %d wall time: %f\n", i, shm_worker_wall[i]); printf(" Worker %d user time: %f\n", i, shm_worker_user[i]); printf(" Worker %d system time: %f\n", i, shm_worker_sys[i]); printf(" Worker %d per-cycle wall time: %.1e\n", i, shm_worker_wall[i] * (double)count_per_cycle / (double)shm_worker_counter[i].value); printf(" Worker %d per-cycle user time: %.1e\n", i, shm_worker_user[i] * (double)count_per_cycle / (double)shm_worker_counter[i].value); printf(" Worker %d per-cycle system time: %.1e\n", i, shm_worker_sys[i] * (double)count_per_cycle / (double)shm_worker_counter[i].value); } printf("Total cycles: %.1e (%llu)\n", (double)total_cycles, total_cycles); printf("Maximum wall time: %f\n", max_wall); printf("Total user time: %f\n", total_user); printf("Total system time: %f\n", total_sys); printf("Concurrency (process vs. wall time): %f\n", (total_user + total_sys) / max_wall); printf("Average per-cycle wall time: %.1e\n", max_wall / (double)total_cycles); printf("Average per-cycle user time: %.1e\n", total_user / (double)total_cycles); printf("Average per-cycle system time: %.1e\n", total_sys / (double)total_cycles); return 0; }
static void nfs_Start_threads(void) { int rc = 0; pthread_attr_t attr_thr; LogDebug(COMPONENT_THREAD, "Starting threads"); /* Init for thread parameter (mostly for scheduling) */ if (pthread_attr_init(&attr_thr) != 0) LogDebug(COMPONENT_THREAD, "can't init pthread's attributes"); if (pthread_attr_setscope(&attr_thr, PTHREAD_SCOPE_SYSTEM) != 0) LogDebug(COMPONENT_THREAD, "can't set pthread's scope"); if (pthread_attr_setdetachstate(&attr_thr, PTHREAD_CREATE_JOINABLE) != 0) LogDebug(COMPONENT_THREAD, "can't set pthread's join state"); LogEvent(COMPONENT_THREAD, "Starting delayed executor."); delayed_start(); /* Starting the thread dedicated to signal handling */ rc = pthread_create(&sigmgr_thrid, &attr_thr, sigmgr_thread, NULL); if (rc != 0) { LogFatal(COMPONENT_THREAD, "Could not create sigmgr_thread, error = %d (%s)", errno, strerror(errno)); } LogDebug(COMPONENT_THREAD, "sigmgr thread started"); rc = worker_init(); if (rc != 0) { LogFatal(COMPONENT_THREAD, "Could not start worker threads: %d", errno); } /* Start event channel service threads */ nfs_rpc_dispatch_threads(&attr_thr); #ifdef _USE_9P /* Starting the 9P/TCP dispatcher thread */ rc = pthread_create(&_9p_dispatcher_thrid, &attr_thr, _9p_dispatcher_thread, NULL); if (rc != 0) { LogFatal(COMPONENT_THREAD, "Could not create 9P/TCP dispatcher, error = %d (%s)", errno, strerror(errno)); } LogEvent(COMPONENT_THREAD, "9P/TCP dispatcher thread was started successfully"); #endif #ifdef _USE_9P_RDMA /* Starting the 9P/RDMA dispatcher thread */ rc = pthread_create(&_9p_rdma_dispatcher_thrid, &attr_thr, _9p_rdma_dispatcher_thread, NULL); if (rc != 0) { LogFatal(COMPONENT_THREAD, "Could not create 9P/RDMA dispatcher, error = %d (%s)", errno, strerror(errno)); } LogEvent(COMPONENT_THREAD, "9P/RDMA dispatcher thread was started successfully"); #endif #ifdef USE_DBUS /* DBUS event thread */ rc = pthread_create(&gsh_dbus_thrid, &attr_thr, gsh_dbus_thread, NULL); if (rc != 0) { LogFatal(COMPONENT_THREAD, "Could not create gsh_dbus_thread, error = %d (%s)", errno, strerror(errno)); } LogEvent(COMPONENT_THREAD, "gsh_dbusthread was started successfully"); #endif /* Starting the admin thread */ rc = pthread_create(&admin_thrid, &attr_thr, admin_thread, NULL); if (rc != 0) { LogFatal(COMPONENT_THREAD, "Could not create admin_thread, error = %d (%s)", errno, strerror(errno)); } LogEvent(COMPONENT_THREAD, "admin thread was started successfully"); /* Starting the reaper thread */ rc = reaper_init(); if (rc != 0) { LogFatal(COMPONENT_THREAD, "Could not create reaper_thread, error = %d (%s)", errno, strerror(errno)); } LogEvent(COMPONENT_THREAD, "reaper thread was started successfully"); /* Starting the general fridge */ rc = general_fridge_init(); if (rc != 0) { LogFatal(COMPONENT_THREAD, "Could not create general fridge, error = %d (%s)", errno, strerror(errno)); } LogEvent(COMPONENT_THREAD, "General fridge was started successfully"); }
/** * Initialize the CDiameterPeer from a configuration file. * The file is kept as dtd. See configdtd.h for the DTD and ConfigExample.xml. * @param cfg_filename - file with the configuration * @returns 1 on success, 0 on error */ int diameter_peer_init(char *cfg_filename) { pid_list_t *i,*j; config = parse_dp_config(cfg_filename); if (!config) { LOG(L_ERR,"ERROR:init_diameter_peer(): Error loading configuration file. Aborting...\n"); goto error; } log_dp_config(L_INFO,config); dp_first_pid = shm_malloc(sizeof(pid_t)); if (!dp_first_pid){ LOG_NO_MEM("shm",sizeof(pid_t)); goto error; } *dp_first_pid = getpid(); shutdownx = shm_malloc(sizeof(int)); if (!shutdownx){ LOG_NO_MEM("shm",sizeof(int)); goto error; } *shutdownx = 0; shutdownx_lock = lock_alloc(); if (!shutdownx_lock){ LOG_NO_MEM("shm",sizeof(gen_lock_t)); goto error; } shutdownx_lock = lock_init(shutdownx_lock); handlers_lock = lock_alloc(); if (!handlers_lock){ LOG_NO_MEM("shm",sizeof(gen_lock_t)); goto error; } handlers_lock = lock_init(handlers_lock); handlers = shm_malloc(sizeof(handler_list)); if (!handlers){ LOG_NO_MEM("shm",sizeof(handler_list)); goto error; } handlers->head=0; handlers->tail=0; /* init the pid list */ pid_list = shm_malloc(sizeof(pid_list_head_t)); pid_list_lock = lock_alloc(); pid_list_lock = lock_init(pid_list_lock); /* init shared mem pointers before forking */ timer_cdp_init(); worker_init(); /* init the peer manager */ peer_manager_init(config); /* init the msg_handler */ //msg_timer_init(); /* init the session */ if (!session_init()) goto error; #ifdef CDP_FOR_SER /* init diameter transactions */ trans_init(); /* add callback for messages - used to implement the API */ cb_add(api_callback,0); #endif /*********** Added by Vitalis to initialize the transactions **********/ /* init diameter transactions */ trans_init(); /* add callback for messages - used to implement the API */ cb_add(api_callback,0); /*******End of addition ***********/ return 1; error: if (shutdownx) shm_free(shutdownx); if (config) free_dp_config(config); i = pid_list->head; while(i){ j = i->next; shm_free(i); i = j; } shm_free(pid_list); lock_get(pid_list_lock); lock_destroy(pid_list_lock); lock_dealloc((void*)pid_list_lock); return 0; }
int main (int argc, char **argv) { srand (time (NULL)); int port = 8080; int work = 4; sighandleall (&signal_handler, SA_RESTART); argv0 = *argv; setname ("cws[master]"); int selfpiperead; { int pipefd[2]; if (pipe (pipefd) == -1) { die("pipe"); } selfpipe = pipefd[1]; selfpiperead = pipefd[0]; } worker_init (port, "file"); spawn_workers (work); tcgetattr (STDIN_FILENO, &old_term); atexit (&cleanup); setterm(); int epollfd = epoll(); epoll_add (epollfd, STDIN_FILENO); epoll_add (epollfd, selfpiperead); struct epoll_event events[MAX_QUEUE]; int i, n; char cmd; while (1) { n = epoll_wait (epollfd, events, MAX_QUEUE, -1); for (i = 0; i < n; i++) { if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN))) { exit(1); } else if (STDIN_FILENO == events[i].data.fd) { // user input event cmd = getchar(); switch (cmd) { case 'k': printf ("Killing workers\n"); finish(1); break; case 'q': printf ("Telling workers to exit\n"); finish(0); break; case '+': spawn_workers (worker_count + 1); break; case '-': spawn_workers (worker_count - 1); break; } } else { // pipe event if (read (selfpiperead, &cmd, 1) <= 0) { die ("read"); } switch (cmd) { case CMD_KILL: printf ("Killing workers\n"); finish(0); break; case CMD_TERM: printf ("Telling workers to exit\n"); finish(1); break; case CMD_INCR: spawn_workers (worker_count + 1); break; case CMD_DECR: spawn_workers (worker_count - 1); break; case CMD_CHLD: check_workers(); break; } } } } return 0; }
void daemon_fork(struct daemon* daemon) { int have_view_respip_cfg = 0; log_assert(daemon); if(!(daemon->views = views_create())) fatal_exit("Could not create views: out of memory"); /* create individual views and their localzone/data trees */ if(!views_apply_cfg(daemon->views, daemon->cfg)) fatal_exit("Could not set up views"); if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->views)) fatal_exit("Could not setup access control list"); if(daemon->cfg->dnscrypt) { #ifdef USE_DNSCRYPT daemon->dnscenv = dnsc_create(); if (!daemon->dnscenv) fatal_exit("dnsc_create failed"); dnsc_apply_cfg(daemon->dnscenv, daemon->cfg); #else fatal_exit("dnscrypt enabled in config but unbound was not built with " "dnscrypt support"); #endif } /* create global local_zones */ if(!(daemon->local_zones = local_zones_create())) fatal_exit("Could not create local zones: out of memory"); if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg)) fatal_exit("Could not set up local zones"); /* process raw response-ip configuration data */ if(!(daemon->respip_set = respip_set_create())) fatal_exit("Could not create response IP set"); if(!respip_global_apply_cfg(daemon->respip_set, daemon->cfg)) fatal_exit("Could not set up response IP set"); if(!respip_views_apply_cfg(daemon->views, daemon->cfg, &have_view_respip_cfg)) fatal_exit("Could not set up per-view response IP sets"); daemon->use_response_ip = !respip_set_is_empty(daemon->respip_set) || have_view_respip_cfg; /* read auth zonefiles */ if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1)) fatal_exit("auth_zones could not be setup"); /* setup modules */ daemon_setup_modules(daemon); /* response-ip-xxx options don't work as expected without the respip * module. To avoid run-time operational surprise we reject such * configuration. */ if(daemon->use_response_ip && modstack_find(&daemon->mods, "respip") < 0) fatal_exit("response-ip options require respip module"); /* first create all the worker structures, so we can pass * them to the newly created threads. */ daemon_create_workers(daemon); #if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP) /* in libev the first inited base gets signals */ if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) fatal_exit("Could not initialize main thread"); #endif /* Now create the threads and init the workers. * By the way, this is thread #0 (the main thread). */ daemon_start_others(daemon); /* Special handling for the main thread. This is the thread * that handles signals and remote control. */ #if !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) /* libevent has the last inited base get signals (or any base) */ if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) fatal_exit("Could not initialize main thread"); #endif signal_handling_playback(daemon->workers[0]); if (!shm_main_init(daemon)) log_warn("SHM has failed"); /* Start resolver service on main thread. */ #ifdef HAVE_SYSTEMD sd_notify(0, "READY=1"); #endif log_info("start of service (%s).", PACKAGE_STRING); worker_work(daemon->workers[0]); #ifdef HAVE_SYSTEMD sd_notify(0, "STOPPING=1"); #endif log_info("service stopped (%s).", PACKAGE_STRING); /* we exited! a signal happened! Stop other threads */ daemon_stop_others(daemon); /* Shutdown SHM */ shm_main_shutdown(daemon); daemon->need_to_exit = daemon->workers[0]->need_to_exit; }
/** * Real initialization, called after the config is parsed */ int diameter_peer_init_real() { pid_list_t *i,*j; if (!config) { LM_ERR("diameter_peer_init_real(): Configuration was not parsed yet. Aborting...\n"); goto error; } log_dp_config(config); dp_first_pid = shm_malloc(sizeof(pid_t)); if (!dp_first_pid){ LOG_NO_MEM("shm",sizeof(pid_t)); goto error; } *dp_first_pid = getpid(); shutdownx = shm_malloc(sizeof(int)); if (!shutdownx){ LOG_NO_MEM("shm",sizeof(int)); goto error; } *shutdownx = 0; shutdownx_lock = lock_alloc(); if (!shutdownx_lock){ LOG_NO_MEM("shm",sizeof(gen_lock_t)); goto error; } shutdownx_lock = lock_init(shutdownx_lock); handlers_lock = lock_alloc(); if (!handlers_lock){ LOG_NO_MEM("shm",sizeof(gen_lock_t)); goto error; } handlers_lock = lock_init(handlers_lock); handlers = shm_malloc(sizeof(handler_list)); if (!handlers){ LOG_NO_MEM("shm",sizeof(handler_list)); goto error; } handlers->head=0; handlers->tail=0; /* init the pid list */ pid_list = shm_malloc(sizeof(pid_list_head_t)); if (!pid_list){ LOG_NO_MEM("shm",sizeof(pid_list_head_t)); goto error; } bzero(pid_list,sizeof(pid_list_head_t)); pid_list_lock = lock_alloc(); pid_list_lock = lock_init(pid_list_lock); /* init shared mem pointers before forking */ timer_cdp_init(); worker_init(); /* init the peer manager */ peer_manager_init(config); /* init diameter transactions */ cdp_trans_init(); /* init the session */ if (!cdp_sessions_init(config->sessions_hash_size)) goto error; /* add callback for messages - used to implement the API */ cb_add(api_callback,0); return 1; error: if (shutdownx) shm_free(shutdownx); if (config) free_dp_config(config); i = pid_list->head; while(i){ j = i->next; shm_free(i); i = j; } shm_free(pid_list); lock_get(pid_list_lock); lock_destroy(pid_list_lock); lock_dealloc((void*)pid_list_lock); return 0; }
int main(int argc, char** argv) { log_file = stdout; init_log(); D("process start"); char ch[80]; D("Start init settings!"); if (argc > 1) { strcpy(conf_file, argv[1]); } else { strcpy(conf_file, "mspc.conf"); } if (pxy_setting_init(conf_file) != 0) { D("settings initialize failed!\n"); return -1; } if (pxy_init_logdb()) { E("init logdb failed!\n"); return -1; } char time[32]; char loggername[64]; db_gettimestr(time, sizeof(time)); sprintf(loggername, "%s:%s:%d", __FILE__, __FUNCTION__, __LINE__); db_insert_log(30000, 0, getpid(), time, loggername, "mspc start...", "", "00000", "", "mspc", setting.ip); if (pxy_init_master() < 0) { E("master initialize failed"); return -1; } D("master initialized"); /* TODO: Maybe we need remove the master-worker mode, seems useless */ if (worker_init()<0) { E("worker #%d initialized failed" , getpid()); return -1; } D("worker inited"); if (worker_start() < 0) { E("worker #%d started failed", getpid()); return -1; } D("worker started"); while(scanf("%s",ch) >= 0 && strcmp(ch,"quit") !=0) { } sleep(5); D("pxy_master_close"); pxy_master_close(); return 1; }
int main(int argc, char **argv) { int option; char *configfile; int background; int mdns_no_rsp; int mdns_no_daap; int loglevel; char *logdomains; char *logfile; char *ffid; char *pidfile; const char *gcry_version; sigset_t sigs; int sigfd; #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) struct kevent ke_sigs[4]; #endif int ret; struct option option_map[] = { { "ffid", 1, NULL, 'b' }, { "debug", 1, NULL, 'd' }, { "logdomains", 1, NULL, 'D' }, { "foreground", 0, NULL, 'f' }, { "config", 1, NULL, 'c' }, { "pidfile", 1, NULL, 'P' }, { "version", 0, NULL, 'v' }, { "mdns-no-rsp", 0, NULL, 512 }, { "mdns-no-daap", 0, NULL, 513 }, { NULL, 0, NULL, 0 } }; configfile = CONFFILE; pidfile = PIDFILE; loglevel = -1; logdomains = NULL; logfile = NULL; background = 1; ffid = NULL; mdns_no_rsp = 0; mdns_no_daap = 0; while ((option = getopt_long(argc, argv, "D:d:c:P:fb:v", option_map, NULL)) != -1) { switch (option) { case 512: mdns_no_rsp = 1; break; case 513: mdns_no_daap = 1; break; case 'b': ffid = optarg; break; case 'd': ret = safe_atoi32(optarg, &option); if (ret < 0) fprintf(stderr, "Error: loglevel must be an integer in '-d %s'\n", optarg); else loglevel = option; break; case 'D': logdomains = optarg; break; case 'f': background = 0; break; case 'c': configfile = optarg; break; case 'P': pidfile = optarg; break; case 'v': version(); return EXIT_SUCCESS; break; default: usage(argv[0]); return EXIT_FAILURE; break; } } ret = logger_init(NULL, NULL, (loglevel < 0) ? E_LOG : loglevel); if (ret != 0) { fprintf(stderr, "Could not initialize log facility\n"); return EXIT_FAILURE; } ret = conffile_load(configfile); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "Config file errors; please fix your config\n"); logger_deinit(); return EXIT_FAILURE; } logger_deinit(); /* Reinit log facility with configfile values */ if (loglevel < 0) loglevel = cfg_getint(cfg_getsec(cfg, "general"), "loglevel"); logfile = cfg_getstr(cfg_getsec(cfg, "general"), "logfile"); ret = logger_init(logfile, logdomains, loglevel); if (ret != 0) { fprintf(stderr, "Could not reinitialize log facility with config file settings\n"); conffile_unload(); return EXIT_FAILURE; } /* Set up libevent logging callback */ event_set_log_callback(logger_libevent); DPRINTF(E_LOG, L_MAIN, "Forked Media Server Version %s taking off\n", VERSION); ret = av_lockmgr_register(ffmpeg_lockmgr); if (ret < 0) { DPRINTF(E_FATAL, L_MAIN, "Could not register ffmpeg lock manager callback\n"); ret = EXIT_FAILURE; goto ffmpeg_init_fail; } av_register_all(); #if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 13) avformat_network_init(); #endif av_log_set_callback(logger_ffmpeg); #ifdef LASTFM /* Initialize libcurl */ curl_global_init(CURL_GLOBAL_DEFAULT); #endif /* Initialize libgcrypt */ gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); gcry_version = gcry_check_version(GCRYPT_VERSION); if (!gcry_version) { DPRINTF(E_FATAL, L_MAIN, "libgcrypt version mismatch\n"); ret = EXIT_FAILURE; goto gcrypt_init_fail; } /* We aren't handling anything sensitive, so give up on secure * memory, which is a scarce system resource. */ gcry_control(GCRYCTL_DISABLE_SECMEM, 0); gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); DPRINTF(E_DBG, L_MAIN, "Initialized with gcrypt %s\n", gcry_version); /* Block signals for all threads except the main one */ sigemptyset(&sigs); sigaddset(&sigs, SIGINT); sigaddset(&sigs, SIGHUP); sigaddset(&sigs, SIGCHLD); sigaddset(&sigs, SIGTERM); sigaddset(&sigs, SIGPIPE); ret = pthread_sigmask(SIG_BLOCK, &sigs, NULL); if (ret != 0) { DPRINTF(E_LOG, L_MAIN, "Error setting signal set\n"); ret = EXIT_FAILURE; goto signal_block_fail; } /* Daemonize and drop privileges */ ret = daemonize(background, pidfile); if (ret < 0) { DPRINTF(E_LOG, L_MAIN, "Could not initialize server\n"); ret = EXIT_FAILURE; goto daemon_fail; } /* Initialize libevent (after forking) */ evbase_main = event_init(); DPRINTF(E_LOG, L_MAIN, "mDNS init\n"); ret = mdns_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "mDNS init failed\n"); ret = EXIT_FAILURE; goto mdns_fail; } /* Initialize the database before starting */ DPRINTF(E_INFO, L_MAIN, "Initializing database\n"); ret = db_init(); if (ret < 0) { DPRINTF(E_FATAL, L_MAIN, "Database init failed\n"); ret = EXIT_FAILURE; goto db_fail; } /* Open a DB connection for the main thread */ ret = db_perthread_init(); if (ret < 0) { DPRINTF(E_FATAL, L_MAIN, "Could not perform perthread DB init for main\n"); ret = EXIT_FAILURE; goto db_fail; } /* Spawn worker thread */ ret = worker_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "Worker thread failed to start\n"); ret = EXIT_FAILURE; goto worker_fail; } /* Spawn cache thread */ ret = cache_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "Cache thread failed to start\n"); ret = EXIT_FAILURE; goto cache_fail; } /* Spawn file scanner thread */ ret = filescanner_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "File scanner thread failed to start\n"); ret = EXIT_FAILURE; goto filescanner_fail; } #ifdef HAVE_SPOTIFY_H /* Spawn Spotify thread */ ret = spotify_init(); if (ret < 0) { DPRINTF(E_INFO, L_MAIN, "Spotify thread not started\n");; } #endif /* Spawn player thread */ ret = player_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "Player thread failed to start\n"); ret = EXIT_FAILURE; goto player_fail; } /* Spawn HTTPd thread */ ret = httpd_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "HTTPd thread failed to start\n"); ret = EXIT_FAILURE; goto httpd_fail; } #ifdef MPD /* Spawn MPD thread */ ret = mpd_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "MPD thread failed to start\n"); ret = EXIT_FAILURE; goto mpd_fail; } #endif /* Start Remote pairing service */ ret = remote_pairing_init(); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "Remote pairing service failed to start\n"); ret = EXIT_FAILURE; goto remote_fail; } /* Register mDNS services */ ret = register_services(ffid, mdns_no_rsp, mdns_no_daap); if (ret < 0) { ret = EXIT_FAILURE; goto mdns_reg_fail; } #if defined(__linux__) /* Set up signal fd */ sigfd = signalfd(-1, &sigs, SFD_NONBLOCK | SFD_CLOEXEC); if (sigfd < 0) { DPRINTF(E_FATAL, L_MAIN, "Could not setup signalfd: %s\n", strerror(errno)); ret = EXIT_FAILURE; goto signalfd_fail; } event_set(&sig_event, sigfd, EV_READ, signal_signalfd_cb, NULL); #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) sigfd = kqueue(); if (sigfd < 0) { DPRINTF(E_FATAL, L_MAIN, "Could not setup kqueue: %s\n", strerror(errno)); ret = EXIT_FAILURE; goto signalfd_fail; } EV_SET(&ke_sigs[0], SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); EV_SET(&ke_sigs[1], SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); EV_SET(&ke_sigs[2], SIGHUP, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); EV_SET(&ke_sigs[3], SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); ret = kevent(sigfd, ke_sigs, 4, NULL, 0, NULL); if (ret < 0) { DPRINTF(E_FATAL, L_MAIN, "Could not register signal events: %s\n", strerror(errno)); ret = EXIT_FAILURE; goto signalfd_fail; } event_set(&sig_event, sigfd, EV_READ, signal_kqueue_cb, NULL); #endif event_base_set(evbase_main, &sig_event); event_add(&sig_event, NULL); /* Run the loop */ event_base_dispatch(evbase_main); DPRINTF(E_LOG, L_MAIN, "Stopping gracefully\n"); ret = EXIT_SUCCESS; /* * On a clean shutdown, bring mDNS down first to give a chance * to the clients to perform a clean shutdown on their end */ DPRINTF(E_LOG, L_MAIN, "mDNS deinit\n"); mdns_deinit(); signalfd_fail: mdns_reg_fail: DPRINTF(E_LOG, L_MAIN, "Remote pairing deinit\n"); remote_pairing_deinit(); remote_fail: DPRINTF(E_LOG, L_MAIN, "HTTPd deinit\n"); httpd_deinit(); httpd_fail: DPRINTF(E_LOG, L_MAIN, "TCPd deinit\n"); #ifdef MPD DPRINTF(E_LOG, L_MAIN, "MPD deinit\n"); mpd_deinit(); mpd_fail: #endif DPRINTF(E_LOG, L_MAIN, "Player deinit\n"); player_deinit(); player_fail: #ifdef HAVE_SPOTIFY_H DPRINTF(E_LOG, L_MAIN, "Spotify deinit\n"); spotify_deinit(); #endif DPRINTF(E_LOG, L_MAIN, "File scanner deinit\n"); filescanner_deinit(); filescanner_fail: DPRINTF(E_LOG, L_MAIN, "Cache deinit\n"); cache_deinit(); cache_fail: DPRINTF(E_LOG, L_MAIN, "Worker deinit\n"); worker_deinit(); worker_fail: DPRINTF(E_LOG, L_MAIN, "Database deinit\n"); db_perthread_deinit(); db_deinit(); db_fail: if (ret == EXIT_FAILURE) { DPRINTF(E_LOG, L_MAIN, "mDNS deinit\n"); mdns_deinit(); } mdns_fail: daemon_fail: if (background) { ret = seteuid(0); if (ret < 0) DPRINTF(E_LOG, L_MAIN, "seteuid() failed: %s\n", strerror(errno)); else { ret = unlink(pidfile); if (ret < 0) DPRINTF(E_LOG, L_MAIN, "Could not unlink PID file %s: %s\n", pidfile, strerror(errno)); } } signal_block_fail: gcrypt_init_fail: #ifdef LASTFM curl_global_cleanup(); #endif #if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 13) avformat_network_deinit(); #endif av_lockmgr_register(NULL); ffmpeg_init_fail: DPRINTF(E_LOG, L_MAIN, "Exiting.\n"); conffile_unload(); logger_deinit(); return ret; }
// public function definitions void *worker(void *threadarg) { assert(threadarg); struct thread_context *context; struct thread_context *contexts; struct thread_context *dispatcher; struct worker_data *data; int rv; struct transaction *transaction = NULL; struct netmap_ring *rxring; void *ring_idx; uint32_t *slots_read; pktbuff *pktbuff_in, *pktbuff_out; int pktbuff_used = 1; struct pcb *pcb; struct msg_hdr *msg_hdr; context = (struct thread_context *)threadarg; contexts = context->shared->contexts; data = context->data; dispatcher = &contexts[context->shared->dispatcher_idx]; rxring = data->rxring; slots_read = bitmap_new(rxring->num_slots); if (!slots_read) pthread_exit(NULL); rv = worker_init(context); if (!rv) { pthread_exit(NULL); } printf("worker[%d]: initialized\n", context->thread_id); // signal to main() that we are initialized atomic_store_explicit(&context->initialized, 1, memory_order_release); for (;;) { if (pktbuff_used) pktbuff_out = pktbuff_allocator_borrow(&data->pktbuff_allocator); if (pktbuff_out) { pktbuff_out->thread_id = context->thread_id; pktbuff_used = 0; // read all the incoming packets while ((rv = tqueue_remove(context->pkt_recv_q, &transaction, &ring_idx)) != TQUEUE_EMPTY) { pktbuff_in = (void *)NETMAP_BUF(rxring, rxring->slot[(uint32_t)ring_idx].buf_idx); recv_pktbuff(pktbuff_in, pktbuff_out, &pcb, &pktbuff_used, context); if (pktbuff_used) { if (send_pktbuff(pktbuff_out, pcb, context, data) < 0) pktbuff_used = 0; } bitmap_set(slots_read, (uint32_t)ring_idx); if (rv == TQUEUE_TRANSACTION_EMPTY) { send_msg_transaction_update(dispatcher, slots_read, rxring->num_slots); bitmap_clearall(slots_read, rxring->num_slots); } } // while (packets) } // pktbuff_out // read all the messages // TODO: handle MSG_ARPD_GET_MAC_REPLY, MSG_PACKET_SENT rv = squeue_enter(context->msg_q, 1); if (!rv) continue; while ((msg_hdr = squeue_get_next_pop_slot(context->msg_q)) != NULL) { switch (msg_hdr->msg_type) { case MSG_PACKET_SENT: pktbuff_allocator_return(&data->pktbuff_allocator, ((struct msg_packet_sent *)msg_hdr)->pktbuff); break; case MSG_ARPD_GET_MAC_REPLY: // for now, just ignore break; default: printf("worker[%d]: unknown message %hu\n", context->thread_id, msg_hdr->msg_type); } } squeue_exit(context->msg_q); usleep(1000); } // for (;;) pthread_exit(NULL); }