opencc_error opencc_errno(void) { if (!lib_initialized) lib_initialize(); return errnum; }
void opencc_perror(const char* spec) { if (!lib_initialized) { lib_initialize(); } perr(spec); perr("\n"); switch (errnum) { case OPENCC_ERROR_VOID: break; case OPENCC_ERROR_DICTLOAD: dictionary_perror(_("Dictionary loading error")); break; case OPENCC_ERROR_CONFIG: config_perror(_("Configuration error")); break; case OPENCC_ERROR_CONVERTER: converter_perror(_("Converter error")); break; case OPENCC_ERROR_ENCODING: perr(_("Encoding error")); break; default: perr(_("Unknown")); } perr("\n"); }
opencc_t opencc_open(const char* config_file) { if (!lib_initialized) { lib_initialize(); } OpenccDesc* opencc; opencc = (OpenccDesc*)malloc(sizeof(OpenccDesc)); opencc->dict_chain = NULL; opencc->converter = converter_open(); converter_set_conversion_mode(opencc->converter, OPENCC_CONVERSION_FAST); if (config_file == NULL) { /* TODO load default */ assert(0); } else { /* Load config */ Config* config = config_open(config_file); if (config == (Config*)-1) { errnum = OPENCC_ERROR_CONFIG; return (opencc_t)-1; } opencc->dict_chain = config_get_dict_chain(config); converter_assign_dictionary(opencc->converter, opencc->dict_chain); config_close(config); } return (opencc_t)opencc; }
opencc_t opencc_open(const char * config_file, const char* home_path) { if (!lib_initialized) lib_initialize(); opencc_desc * opencc; opencc = (opencc_desc *) malloc(sizeof(opencc_desc)); opencc->dictionary_set = NULL; opencc->converter = converter_open(); converter_set_conversion_mode(opencc->converter, OPENCC_CONVERSION_FAST); /* 加載默認辭典 */ int retval; if (config_file == NULL) retval = 0; else { config_t config = config_open(config_file, home_path); if (config == (config_t) -1) { errnum = OPENCC_ERROR_CONFIG; return (opencc_t) -1; } opencc->dictionary_set = config_get_dictionary_set(config); converter_assign_dictionary(opencc->converter, opencc->dictionary_set); config_close(config); } return (opencc_t) opencc; }
int opencc_dict_load(opencc_t t_opencc, const char * dict_filename, opencc_dictionary_type dict_type) { if (!lib_initialized) lib_initialize(); opencc_desc * opencc = (opencc_desc *) t_opencc; dictionary_group_t dictionary_group; if (opencc->dictionary_set == NULL) { opencc->dictionary_set = dictionary_set_open(); dictionary_group = dictionary_set_new_group(opencc->dictionary_set); } else { dictionary_group = dictionary_set_get_group(opencc->dictionary_set, 0); } int retval; retval = dictionary_group_load(dictionary_group, dict_filename, dict_type); if (retval == -1) { errnum = OPENCC_ERROR_DICTLOAD; return -1; } converter_assign_dictionary(opencc->converter, opencc->dictionary_set); return retval; }
void opencc_set_conversion_mode(opencc_t t_opencc, opencc_conversion_mode conversion_mode) { if (!lib_initialized) { lib_initialize(); } OpenccDesc* opencc = (OpenccDesc*)t_opencc; converter_set_conversion_mode(opencc->converter, conversion_mode); }
int opencc_close(opencc_t t_opencc) { if (!lib_initialized) { lib_initialize(); } OpenccDesc* opencc = (OpenccDesc*)t_opencc; converter_close(opencc->converter); if (opencc->dict_chain != NULL) { dict_chain_delete(opencc->dict_chain); } free(opencc); return 0; }
int opencc_close(opencc_t t_opencc) { if (!lib_initialized) lib_initialize(); opencc_desc * opencc = (opencc_desc *) t_opencc; converter_close(opencc->converter); if (opencc->dictionary_set != NULL) dictionary_set_close(opencc->dictionary_set); free(opencc); return 0; }
size_t opencc_convert(opencc_t t_opencc, ucs4_t ** inbuf, size_t * inbuf_left, ucs4_t ** outbuf, size_t * outbuf_left) { if (!lib_initialized) lib_initialize(); opencc_desc * opencc = (opencc_desc *) t_opencc; size_t retval = converter_convert (opencc->converter, inbuf, inbuf_left, outbuf, outbuf_left); if (retval == (size_t) -1) errnum = OPENCC_ERROR_CONVERTER; return retval; }
int opencc_dict_load(opencc_t t_opencc, const char* dict_filename, opencc_dictionary_type dict_type) { if (!lib_initialized) { lib_initialize(); } OpenccDesc* opencc = (OpenccDesc*)t_opencc; DictGroup* DictGroup; if (opencc->dict_chain == NULL) { opencc->dict_chain = dict_chain_new(NULL); DictGroup = dict_chain_add_group(opencc->dict_chain); } else { DictGroup = dict_chain_get_group(opencc->dict_chain, 0); } int retval = dict_group_load(DictGroup, dict_filename, dict_type); if (retval == -1) { errnum = OPENCC_ERROR_DICTLOAD; return -1; } converter_assign_dictionary(opencc->converter, opencc->dict_chain); return retval; }
char* opencc_convert_utf8(opencc_t t_opencc, const char* inbuf, size_t length) { if (!lib_initialized) { lib_initialize(); } size_t actual_length = strlen(inbuf); if ((length == (size_t)-1) || (length > actual_length)) { length = actual_length; } ucs4_t* winbuf = utf8_to_ucs4(inbuf, length); if (winbuf == (ucs4_t*)-1) { /* Can not convert input UTF8 to UCS4 */ errnum = OPENCC_ERROR_ENCODING; return (char*)-1; } /* Set up UTF8 buffer */ size_t outbuf_len = length; size_t outsize = outbuf_len; char* original_outbuf = (char*)malloc(sizeof(char) * (outbuf_len + 1)); char* outbuf = original_outbuf; original_outbuf[0] = '\0'; /* Set conversion buffer */ size_t wbufsize = length + 64; ucs4_t* woutbuf = (ucs4_t*)malloc(sizeof(ucs4_t) * (wbufsize + 1)); ucs4_t* pinbuf = winbuf; ucs4_t* poutbuf = woutbuf; size_t inbuf_left, outbuf_left; inbuf_left = ucs4len(winbuf); outbuf_left = wbufsize; while (inbuf_left > 0) { size_t retval = opencc_convert(t_opencc, &pinbuf, &inbuf_left, &poutbuf, &outbuf_left); if (retval == (size_t)-1) { free(outbuf); free(winbuf); free(woutbuf); return (char*)-1; } *poutbuf = L'\0'; char* ubuff = ucs4_to_utf8(woutbuf, (size_t)-1); if (ubuff == (char*)-1) { free(outbuf); free(winbuf); free(woutbuf); errnum = OPENCC_ERROR_ENCODING; return (char*)-1; } size_t ubuff_len = strlen(ubuff); while (ubuff_len > outsize) { size_t outbuf_offset = outbuf - original_outbuf; outsize += outbuf_len; outbuf_len += outbuf_len; original_outbuf = (char*)realloc(original_outbuf, sizeof(char) * outbuf_len); outbuf = original_outbuf + outbuf_offset; } strncpy(outbuf, ubuff, ubuff_len); free(ubuff); outbuf += ubuff_len; *outbuf = '\0'; outbuf_left = wbufsize; poutbuf = woutbuf; } free(winbuf); free(woutbuf); original_outbuf = (char*)realloc(original_outbuf, sizeof(char) * (strlen(original_outbuf) + 1)); return original_outbuf; }
char * opencc_convert_utf8(opencc_t t_opencc, const char * inbuf, size_t length) { if (!lib_initialized) lib_initialize(); if (length == (size_t) -1 || length > strlen(inbuf)) length = strlen(inbuf); /* 將輸入數據轉換爲ucs4_t字符串 */ ucs4_t * winbuf = utf8_to_ucs4(inbuf, length); if (winbuf == (ucs4_t *) -1) { /* 輸入數據轉換失敗 */ errnum = OPENCC_ERROR_ENCODIND; return (char *) -1; } /* 設置輸出UTF8文本緩衝區空間 */ size_t outbuf_len = length; size_t outsize = outbuf_len; char * original_outbuf = (char *) malloc(sizeof(char) * (outbuf_len + 1)); char * outbuf = original_outbuf; original_outbuf[0] = '\0'; /* 設置轉換緩衝區空間 */ size_t wbufsize = length + 64; ucs4_t * woutbuf = (ucs4_t *) malloc(sizeof(ucs4_t) * (wbufsize + 1)); ucs4_t * pinbuf = winbuf; ucs4_t * poutbuf = woutbuf; size_t inbuf_left, outbuf_left; inbuf_left = ucs4len(winbuf); outbuf_left = wbufsize; while (inbuf_left > 0) { size_t retval = opencc_convert(t_opencc, &pinbuf, &inbuf_left, &poutbuf, &outbuf_left); if (retval == (size_t) -1) { free(outbuf); free(winbuf); free(woutbuf); return (char *) -1; } *poutbuf = L'\0'; char * ubuff = ucs4_to_utf8(woutbuf, (size_t) -1); if (ubuff == (char *) -1) { free(outbuf); free(winbuf); free(woutbuf); errnum = OPENCC_ERROR_ENCODIND; return (char *) -1; } size_t ubuff_len = strlen(ubuff); while (ubuff_len > outsize) { size_t outbuf_offset = outbuf - original_outbuf; outsize += outbuf_len; outbuf_len += outbuf_len; original_outbuf = (char *) realloc(original_outbuf, sizeof(char) * outbuf_len); outbuf = original_outbuf + outbuf_offset; } strncpy(outbuf, ubuff, ubuff_len); free(ubuff); outbuf += ubuff_len; *outbuf = '\0'; outbuf_left = wbufsize; poutbuf = woutbuf; } free(winbuf); free(woutbuf); original_outbuf = (char *) realloc(original_outbuf, sizeof(char) * (strlen(original_outbuf) + 1)); return original_outbuf; }
void os_start(void) { int i; slldbg("Entry\n"); /* 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_delayeddeallocations); /* 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; g_pidhash[ PIDHASH(0)].pid = 0; /* 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(_TCB)); g_idletcb.task_state = TSTATE_TASK_RUNNING; g_idletcb.entry.main = (main_t)os_start; #if CONFIG_TASK_NAME_SIZE > 0 strncpy(g_idletcb.name, g_idlename, CONFIG_TASK_NAME_SIZE-1); g_idletcb.argv[0] = g_idletcb.name; #else g_idletcb.argv[0] = (char*)g_idlename; #endif /* CONFIG_TASK_NAME_SIZE */ /* 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 */ g_idletcb.flags = TCB_FLAG_TTYPE_KERNEL; up_initial_state(&g_idletcb); /* Initialize the semaphore facility(if in link). This has to be done * very early because many subsystems depend upon fully functional * semaphores. */ #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (sem_initialize != NULL) #endif { sem_initialize(); } /* Initialize the memory manager */ #ifndef CONFIG_HEAP_BASE { FAR void *heap_start; size_t heap_size; up_allocate_heap(&heap_start, &heap_size); kmm_initialize(heap_start, heap_size); } #else kmm_initialize((void*)CONFIG_HEAP_BASE, CONFIG_HEAP_SIZE); #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) */ #ifndef CONFIG_DISABLE_CLOCK #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (clock_initialize != NULL) #endif { clock_initialize(); } #endif #ifndef CONFIG_DISABLE_POSIX_TIMERS #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (timer_initialize != NULL) #endif { timer_initialize(); } #endif /* Initialize the signal facility (if in link) */ #ifndef CONFIG_DISABLE_SIGNALS #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (sig_initialize != NULL) #endif { sig_initialize(); } #endif /* Initialize the named message queue facility (if in link) */ #ifndef CONFIG_DISABLE_MQUEUE #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (mq_initialize != NULL) #endif { mq_initialize(); } #endif /* Initialize the thread-specific data facility (if in link) */ #ifndef CONFIG_DISABLE_PTHREAD #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (pthread_initialize != NULL) #endif { pthread_initialize(); } #endif /* Initialize the file system (needed to support device drivers) */ #if CONFIG_NFILE_DESCRIPTORS > 0 #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (fs_initialize != NULL) #endif { fs_initialize(); } #endif /* Initialize the network system */ #ifdef CONFIG_NET #if 0 if (net_initialize != NULL) #endif { net_initialize(); } #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(); /* Initialize the C libraries (if included in the link). This * is done last because the libraries may depend on the above. */ #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (lib_initialize != NULL) #endif { lib_initialize(); } /* Create stdout, stderr, stdin on the IDLE task. These will be * inherited by all of the threads created by the IDLE task. */ (void)sched_setupidlefiles(&g_idletcb); /* Create initial tasks and bring-up the system */ (void)os_bringup(); /* 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! */ if (kmm_trysemaphore() == 0) { sched_garbagecollection(); kmm_givesemaphore(); } #endif /* Perform any processor-specific idle state operations */ up_idle(); } }
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(); } }