int clone_group (struct group **gp, struct group *group, const char *file, int line) { struct group *g = (struct group *)0; /* Normally gp should contain the null pointer, but for convenience it's permissible to clone a group into itself. */ if (*gp && *gp != group) return 0; if (!group_allocate (&g, file, line)) return 0; if (group == *gp) *gp = (struct group *)0; group_reference (gp, g, file, line); g -> authoritative = group -> authoritative; group_reference (&g -> next, group, file, line); group_dereference (&g, file, line); return 1; }
int task_init(FAR struct tcb_s *tcb, const char *name, int priority, FAR uint32_t *stack, uint32_t stack_size, main_t entry, FAR char * const argv[]) { FAR struct task_tcb_s *ttcb = (FAR struct task_tcb_s *)tcb; int errcode; int ret; /* Only tasks and kernel threads can be initialized in this way */ #ifndef CONFIG_DISABLE_PTHREAD DEBUGASSERT(tcb && (tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD); #endif /* Create a new task group */ #ifdef HAVE_TASK_GROUP ret = group_allocate(ttcb, tcb->flags); if (ret < 0) { errcode = -ret; goto errout; } #endif /* Associate file descriptors with the new task */ #if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 ret = group_setuptaskfiles(ttcb); if (ret < 0) { errcode = -ret; goto errout_with_group; } #endif /* Configure the user provided stack region */ up_use_stack(tcb, stack, stack_size); /* Initialize the task control block */ ret = task_schedsetup(ttcb, priority, task_start, entry, TCB_FLAG_TTYPE_TASK); if (ret < OK) { errcode = -ret; goto errout_with_group; } /* Setup to pass parameters to the new task */ (void)task_argsetup(ttcb, name, argv); /* Now we have enough in place that we can join the group */ #ifdef HAVE_TASK_GROUP ret = group_initialize(ttcb); if (ret < 0) { errcode = -ret; goto errout_with_group; } #endif return OK; errout_with_group: #ifdef HAVE_TASK_GROUP group_leave(tcb); errout: #endif set_errno(errcode); return ERROR; }
isc_result_t read_client_conf () { struct client_config *config; struct client_state *state; struct interface_info *ip; isc_result_t status; /* Set up the initial dhcp option universe. */ initialize_common_option_spaces (); /* Initialize the top level client configuration. */ memset (&top_level_config, 0, sizeof top_level_config); /* Set some defaults... */ top_level_config.timeout = 60; top_level_config.select_interval = 0; top_level_config.reboot_timeout = 10; top_level_config.retry_interval = 300; top_level_config.backoff_cutoff = 15; top_level_config.initial_interval = 3; top_level_config.bootp_policy = P_ACCEPT; top_level_config.script_name = path_dhclient_script; top_level_config.requested_options = default_requested_options; top_level_config.omapi_port = -1; top_level_config.do_forward_update = 1; group_allocate (&top_level_config.on_receipt, MDL); if (!top_level_config.on_receipt) log_fatal ("no memory for top-level on_receipt group"); group_allocate (&top_level_config.on_transmission, MDL); if (!top_level_config.on_transmission) log_fatal ("no memory for top-level on_transmission group"); status = read_client_conf_file (path_dhclient_conf, (struct interface_info *)0, &top_level_config); if (status != ISC_R_SUCCESS) { ; #ifdef LATER /* Set up the standard name service updater routine. */ parse = (struct parse *)0; status = new_parse (&parse, -1, default_client_config, (sizeof default_client_config) - 1, "default client configuration", 0); if (status != ISC_R_SUCCESS) log_fatal ("can't begin default client config!"); do { token = peek_token (&val, (unsigned *)0, cfile); if (token == END_OF_FILE) break; parse_client_statement (cfile, (struct interface_info *)0, &top_level_config); } while (1); end_parse (&parse); #endif } /* Set up state and config structures for clients that don't have per-interface configuration statements. */ config = (struct client_config *)0; for (ip = interfaces; ip; ip = ip -> next) { if (!ip -> client) { ip -> client = (struct client_state *) dmalloc (sizeof (struct client_state), MDL); if (!ip -> client) log_fatal ("no memory for client state."); memset (ip -> client, 0, sizeof *(ip -> client)); ip -> client -> interface = ip; } if (!ip -> client -> config) { if (!config) { config = (struct client_config *) dmalloc (sizeof (struct client_config), MDL); if (!config) log_fatal ("no memory for client config."); memcpy (config, &top_level_config, sizeof top_level_config); } ip -> client -> config = config; } } return status; }
void os_start(void) { int i; slldbg("Entry\n"); /* Initialize RTOS Data ***************************************************/ /* Initialize all task lists */ dq_init(&g_readytorun); dq_init(&g_pendingtasks); dq_init(&g_waitingforsemaphore); #ifndef CONFIG_DISABLE_SIGNALS dq_init(&g_waitingforsignal); #endif #ifndef CONFIG_DISABLE_MQUEUE dq_init(&g_waitingformqnotfull); dq_init(&g_waitingformqnotempty); #endif #ifdef CONFIG_PAGING dq_init(&g_waitingforfill); #endif dq_init(&g_inactivetasks); sq_init(&g_delayed_kufree); #if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \ defined(CONFIG_MM_KERNEL_HEAP) sq_init(&g_delayed_kfree); #endif /* Initialize the logic that determine unique process IDs. */ g_lastpid = 0; for (i = 0; i < CONFIG_MAX_TASKS; i++) { g_pidhash[i].tcb = NULL; g_pidhash[i].pid = INVALID_PROCESS_ID; } /* Assign the process ID of ZERO to the idle task */ g_pidhash[PIDHASH(0)].tcb = &g_idletcb.cmn; g_pidhash[PIDHASH(0)].pid = 0; /* Initialize the IDLE task TCB *******************************************/ /* Initialize a TCB for this thread of execution. NOTE: The default * value for most components of the g_idletcb are zero. The entire * structure is set to zero. Then only the (potentially) non-zero * elements are initialized. NOTE: The idle task is the only task in * that has pid == 0 and sched_priority == 0. */ bzero((void*)&g_idletcb, sizeof(struct task_tcb_s)); g_idletcb.cmn.task_state = TSTATE_TASK_RUNNING; g_idletcb.cmn.entry.main = (main_t)os_start; g_idletcb.cmn.flags = TCB_FLAG_TTYPE_KERNEL; /* Set the IDLE task name */ #if CONFIG_TASK_NAME_SIZE > 0 strncpy(g_idletcb.cmn.name, g_idlename, CONFIG_TASK_NAME_SIZE); g_idletcb.cmn.name[CONFIG_TASK_NAME_SIZE] = '\0'; #endif /* CONFIG_TASK_NAME_SIZE */ /* Configure the task name in the argument list. The IDLE task does * not really have an argument list, but this name is still useful * for things like the NSH PS command. * * In the kernel mode build, the arguments are saved on the task's stack * and there is no support that yet. */ #if CONFIG_TASK_NAME_SIZE > 0 g_idleargv[0] = g_idletcb.cmn.name; #else g_idleargv[0] = (FAR char *)g_idlename; #endif /* CONFIG_TASK_NAME_SIZE */ g_idleargv[1] = NULL; g_idletcb.argv = g_idleargv; /* Then add the idle task's TCB to the head of the ready to run list */ dq_addfirst((FAR dq_entry_t*)&g_idletcb, (FAR dq_queue_t*)&g_readytorun); /* Initialize the processor-specific portion of the TCB */ up_initial_state(&g_idletcb.cmn); /* Initialize RTOS facilities *********************************************/ /* Initialize the semaphore facility. This has to be done very early * because many subsystems depend upon fully functional semaphores. */ sem_initialize(); #if defined(MM_KERNEL_USRHEAP_INIT) || defined(CONFIG_MM_KERNEL_HEAP) || defined(CONFIG_MM_PGALLOC) /* Initialize the memory manager */ { FAR void *heap_start; size_t heap_size; #ifdef MM_KERNEL_USRHEAP_INIT /* Get the user-mode heap from the platform specific code and configure * the user-mode memory allocator. */ up_allocate_heap(&heap_start, &heap_size); kumm_initialize(heap_start, heap_size); #endif #ifdef CONFIG_MM_KERNEL_HEAP /* Get the kernel-mode heap from the platform specific code and configure * the kernel-mode memory allocator. */ up_allocate_kheap(&heap_start, &heap_size); kmm_initialize(heap_start, heap_size); #endif #ifdef CONFIG_MM_PGALLOC /* If there is a page allocator in the configuration, then get the page * heap information from the platform-specific code and configure the * page allocator. */ up_allocate_pgheap(&heap_start, &heap_size); mm_pginitialize(heap_start, heap_size); #endif } #endif #if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS) /* Initialize tasking data structures */ #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (task_initialize != NULL) #endif { task_initialize(); } #endif /* Initialize the interrupt handling subsystem (if included) */ #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (irq_initialize != NULL) #endif { irq_initialize(); } /* Initialize the watchdog facility (if included in the link) */ #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (wd_initialize != NULL) #endif { wd_initialize(); } /* Initialize the POSIX timer facility (if included in the link) */ #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (clock_initialize != NULL) #endif { clock_initialize(); } #ifndef CONFIG_DISABLE_POSIX_TIMERS #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (timer_initialize != NULL) #endif { timer_initialize(); } #endif #ifndef CONFIG_DISABLE_SIGNALS /* Initialize the signal facility (if in link) */ #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (sig_initialize != NULL) #endif { sig_initialize(); } #endif #ifndef CONFIG_DISABLE_MQUEUE /* Initialize the named message queue facility (if in link) */ #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (mq_initialize != NULL) #endif { mq_initialize(); } #endif #ifndef CONFIG_DISABLE_PTHREAD /* Initialize the thread-specific data facility (if in link) */ #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (pthread_initialize != NULL) #endif { pthread_initialize(); } #endif #if CONFIG_NFILE_DESCRIPTORS > 0 /* Initialize the file system (needed to support device drivers) */ fs_initialize(); #endif #ifdef CONFIG_NET /* Initialize the networking system. Network initialization is * performed in two steps: (1) net_setup() initializes static * configuration of the network support. This must be done prior * to registering network drivers by up_initialize(). This step * cannot require upon any hardware-depending features such as * timers or interrupts. */ net_setup(); #endif /* The processor specific details of running the operating system * will be handled here. Such things as setting up interrupt * service routines and starting the clock are some of the things * that are different for each processor and hardware platform. */ up_initialize(); #ifdef CONFIG_NET /* Complete initialization the networking system now that interrupts * and timers have been configured by up_initialize(). */ net_initialize(); #endif #ifdef CONFIG_MM_SHM /* Initialize shared memory support */ shm_initialize(); #endif /* Initialize the C libraries. This is done last because the libraries * may depend on the above. */ lib_initialize(); /* IDLE Group Initialization **********************************************/ #ifdef HAVE_TASK_GROUP /* Allocate the IDLE group */ DEBUGVERIFY(group_allocate(&g_idletcb, g_idletcb.cmn.flags)); #endif #if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 /* Create stdout, stderr, stdin on the IDLE task. These will be * inherited by all of the threads created by the IDLE task. */ DEBUGVERIFY(group_setupidlefiles(&g_idletcb)); #endif #ifdef HAVE_TASK_GROUP /* Complete initialization of the IDLE group. Suppress retention * of child status in the IDLE group. */ DEBUGVERIFY(group_initialize(&g_idletcb)); g_idletcb.cmn.group->tg_flags = GROUP_FLAG_NOCLDWAIT; #endif /* Bring Up the System ****************************************************/ /* Create initial tasks and bring-up the system */ DEBUGVERIFY(os_bringup()); /* The IDLE Loop **********************************************************/ /* When control is return to this point, the system is idle. */ sdbg("Beginning Idle Loop\n"); for (;;) { /* Perform garbage collection (if it is not being done by the worker * thread). This cleans-up memory de-allocations that were queued * because they could not be freed in that execution context (for * example, if the memory was freed from an interrupt handler). */ #ifndef CONFIG_SCHED_WORKQUEUE /* We must have exclusive access to the memory manager to do this * BUT the idle task cannot wait on a semaphore. So we only do * the cleanup now if we can get the semaphore -- this should be * possible because if the IDLE thread is running, no other task is! * * WARNING: This logic could have undesirable side-effects if priority * inheritance is enabled. Imaginee the possible issues if the * priority of the IDLE thread were to get boosted! Moral: If you * use priority inheritance, then you should also enable the work * queue so that is done in a safer context. */ if (kmm_trysemaphore() == 0) { sched_garbagecollection(); kmm_givesemaphore(); } #endif /* Perform any processor-specific idle state operations */ up_idle(); } }
static int thread_create(FAR const char *name, uint8_t ttype, int priority, int stack_size, main_t entry, FAR char * const argv[]) { FAR struct task_tcb_s *tcb; pid_t pid; int errcode; int ret; /* Allocate a TCB for the new task. */ tcb = (FAR struct task_tcb_s *)kmm_zalloc(sizeof(struct task_tcb_s)); if (!tcb) { sdbg("ERROR: Failed to allocate TCB\n"); errcode = ENOMEM; goto errout; } /* Allocate a new task group with privileges appropriate for the parent * thread type. */ #ifdef HAVE_TASK_GROUP ret = group_allocate(tcb, ttype); if (ret < 0) { errcode = -ret; goto errout_with_tcb; } #endif /* Associate file descriptors with the new task */ #if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 ret = group_setuptaskfiles(tcb); if (ret < OK) { errcode = -ret; goto errout_with_tcb; } #endif /* Allocate the stack for the TCB */ ret = up_create_stack((FAR struct tcb_s *)tcb, stack_size, ttype); if (ret < OK) { errcode = -ret; goto errout_with_tcb; } /* Initialize the task control block */ ret = task_schedsetup(tcb, priority, task_start, entry, ttype); if (ret < OK) { errcode = -ret; goto errout_with_tcb; } /* Setup to pass parameters to the new task */ (void)task_argsetup(tcb, name, argv); /* Now we have enough in place that we can join the group */ #ifdef HAVE_TASK_GROUP ret = group_initialize(tcb); if (ret < 0) { errcode = -ret; goto errout_with_tcb; } #endif /* Get the assigned pid before we start the task */ pid = (int)tcb->cmn.pid; /* Activate the task */ ret = task_activate((FAR struct tcb_s *)tcb); if (ret < OK) { errcode = get_errno(); /* The TCB was added to the active task list by task_schedsetup() */ dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks); goto errout_with_tcb; } return pid; errout_with_tcb: sched_releasetcb((FAR struct tcb_s *)tcb, ttype); errout: set_errno(errcode); return ERROR; }
FAR struct task_tcb_s *task_vforksetup(start_t retaddr) { struct tcb_s *parent = this_task(); struct task_tcb_s *child; uint8_t ttype; int priority; int ret; DEBUGASSERT(retaddr); /* Get the type of the fork'ed task (kernel or user) */ if ((parent->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL) { /* Fork'ed from a kernel thread */ ttype = TCB_FLAG_TTYPE_KERNEL; } else { /* Fork'ed from a user task or pthread */ ttype = TCB_FLAG_TTYPE_TASK; } /* Allocate a TCB for the child task. */ child = (FAR struct task_tcb_s *)kmm_zalloc(sizeof(struct task_tcb_s)); if (!child) { serr("ERROR: Failed to allocate TCB\n"); set_errno(ENOMEM); return NULL; } /* Allocate a new task group with the same privileges as the parent */ #ifdef HAVE_TASK_GROUP ret = group_allocate(child, parent->flags); if (ret < 0) { goto errout_with_tcb; } #endif /* Associate file descriptors with the new task */ #if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 ret = group_setuptaskfiles(child); if (ret < OK) { goto errout_with_tcb; } #endif /* Get the priority of the parent task */ #ifdef CONFIG_PRIORITY_INHERITANCE priority = parent->base_priority; /* "Normal," unboosted priority */ #else priority = parent->sched_priority; /* Current priority */ #endif /* Initialize the task control block. This calls up_initial_state() */ sinfo("Child priority=%d start=%p\n", priority, retaddr); ret = task_schedsetup(child, priority, retaddr, parent->entry.main, ttype); if (ret < OK) { goto errout_with_tcb; } sinfo("parent=%p, returning child=%p\n", parent, child); return child; errout_with_tcb: sched_releasetcb((FAR struct tcb_s *)child, ttype); set_errno(-ret); return NULL; }
isc_result_t read_client_conf () { struct client_config *config; struct interface_info *ip; isc_result_t status; unsigned code; /* Initialize the default request list. */ memset(default_requested_options, 0, sizeof(default_requested_options)); /* 1 */ code = DHO_SUBNET_MASK; option_code_hash_lookup(&default_requested_options[0], dhcp_universe.code_hash, &code, 0, MDL); /* 2 */ code = DHO_BROADCAST_ADDRESS; option_code_hash_lookup(&default_requested_options[1], dhcp_universe.code_hash, &code, 0, MDL); /* 3 */ code = DHO_TIME_OFFSET; option_code_hash_lookup(&default_requested_options[2], dhcp_universe.code_hash, &code, 0, MDL); /* 4 */ code = DHO_ROUTERS; option_code_hash_lookup(&default_requested_options[3], dhcp_universe.code_hash, &code, 0, MDL); /* 5 */ code = DHO_DOMAIN_NAME; option_code_hash_lookup(&default_requested_options[4], dhcp_universe.code_hash, &code, 0, MDL); /* 6 */ code = DHO_DOMAIN_NAME_SERVERS; option_code_hash_lookup(&default_requested_options[5], dhcp_universe.code_hash, &code, 0, MDL); /* 7 */ code = DHO_HOST_NAME; option_code_hash_lookup(&default_requested_options[6], dhcp_universe.code_hash, &code, 0, MDL); /* 8 */ code = D6O_NAME_SERVERS; option_code_hash_lookup(&default_requested_options[7], dhcpv6_universe.code_hash, &code, 0, MDL); /* 9 */ code = D6O_DOMAIN_SEARCH; option_code_hash_lookup(&default_requested_options[8], dhcpv6_universe.code_hash, &code, 0, MDL); for (code = 0 ; code < NUM_DEFAULT_REQUESTED_OPTS ; code++) { if (default_requested_options[code] == NULL) log_fatal("Unable to find option definition for " "index %u during default parameter request " "assembly.", code); } /* Initialize the top level client configuration. */ memset (&top_level_config, 0, sizeof top_level_config); /* Set some defaults... */ top_level_config.timeout = 60; top_level_config.select_interval = 0; top_level_config.reboot_timeout = 10; top_level_config.retry_interval = 300; top_level_config.backoff_cutoff = 15; top_level_config.initial_interval = 3; top_level_config.bootp_policy = P_ACCEPT; top_level_config.script_name = path_dhclient_script; top_level_config.requested_options = default_requested_options; top_level_config.omapi_port = -1; #if defined (NSUPDATE) top_level_config.do_forward_update = 1; #endif /* Requested lease time, used by DHCPv6 (DHCPv4 uses the option cache) */ top_level_config.requested_lease = 7200; group_allocate (&top_level_config.on_receipt, MDL); if (!top_level_config.on_receipt) log_fatal ("no memory for top-level on_receipt group"); group_allocate (&top_level_config.on_transmission, MDL); if (!top_level_config.on_transmission) log_fatal ("no memory for top-level on_transmission group"); status = read_client_conf_file (path_dhclient_conf, (struct interface_info *)0, &top_level_config); if (status != ISC_R_SUCCESS) { ; #ifdef LATER /* Set up the standard name service updater routine. */ parse = (struct parse *)0; status = new_parse (&parse, -1, default_client_config, (sizeof default_client_config) - 1, "default client configuration", 0); if (status != ISC_R_SUCCESS) log_fatal ("can't begin default client config!"); do { token = peek_token (&val, (unsigned *)0, cfile); if (token == END_OF_FILE) break; parse_client_statement (cfile, (struct interface_info *)0, &top_level_config); } while (1); end_parse (&parse); #endif } /* Set up state and config structures for clients that don't have per-interface configuration statements. */ config = (struct client_config *)0; for (ip = interfaces; ip; ip = ip -> next) { if (!ip -> client) { ip -> client = (struct client_state *) dmalloc (sizeof (struct client_state), MDL); if (!ip -> client) log_fatal ("no memory for client state."); memset (ip -> client, 0, sizeof *(ip -> client)); ip -> client -> interface = ip; } if (!ip -> client -> config) { if (!config) { config = (struct client_config *) dmalloc (sizeof (struct client_config), MDL); if (!config) log_fatal ("no memory for client config."); memcpy (config, &top_level_config, sizeof top_level_config); } ip -> client -> config = config; } } return status; }