static void ListerThread(struct ListerParams *args) { int found_parent = 0; pid_t clone_pid = sys_gettid(), ppid = sys_getppid(); char proc_self_task[80], marker_name[48], *marker_path; const char *proc_paths[3]; const char *const *proc_path = proc_paths; int proc = -1, marker = -1, num_threads = 0; int max_threads = 0, sig; struct kernel_stat marker_sb, proc_sb; stack_t altstack; /* Create "marker" that we can use to detect threads sharing the same * address space and the same file handles. By setting the FD_CLOEXEC flag * we minimize the risk of misidentifying child processes as threads; * and since there is still a race condition, we will filter those out * later, anyway. */ if ((marker = sys_socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0 || sys_fcntl(marker, F_SETFD, FD_CLOEXEC) < 0) { failure: args->result = -1; args->err = errno; if (marker >= 0) NO_INTR(sys_close(marker)); sig_marker = marker = -1; if (proc >= 0) NO_INTR(sys_close(proc)); sig_proc = proc = -1; sys__exit(1); } /* Compute search paths for finding thread directories in /proc */ local_itoa(strrchr(strcpy(proc_self_task, "/proc/"), '\000'), ppid); strcpy(marker_name, proc_self_task); marker_path = marker_name + strlen(marker_name); strcat(proc_self_task, "/task/"); proc_paths[0] = proc_self_task; /* /proc/$$/task/ */ proc_paths[1] = "/proc/"; /* /proc/ */ proc_paths[2] = NULL; /* Compute path for marker socket in /proc */ local_itoa(strcpy(marker_path, "/fd/") + 4, marker); if (sys_stat(marker_name, &marker_sb) < 0) { goto failure; } /* Catch signals on an alternate pre-allocated stack. This way, we can * safely execute the signal handler even if we ran out of memory. */ memset(&altstack, 0, sizeof(altstack)); altstack.ss_sp = args->altstack_mem; altstack.ss_flags = 0; altstack.ss_size = ALT_STACKSIZE; sys_sigaltstack(&altstack, (const stack_t *)NULL); /* Some kernels forget to wake up traced processes, when the * tracer dies. So, intercept synchronous signals and make sure * that we wake up our tracees before dying. It is the caller's * responsibility to ensure that asynchronous signals do not * interfere with this function. */ sig_marker = marker; sig_proc = -1; for (sig = 0; sig < sizeof(sync_signals)/sizeof(*sync_signals); sig++) { struct kernel_sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_sigaction_ = SignalHandler; sys_sigfillset(&sa.sa_mask); sa.sa_flags = SA_ONSTACK|SA_SIGINFO|SA_RESETHAND; sys_sigaction(sync_signals[sig], &sa, (struct kernel_sigaction *)NULL); } /* Read process directories in /proc/... */ for (;;) { /* Some kernels know about threads, and hide them in "/proc" * (although they are still there, if you know the process * id). Threads are moved into a separate "task" directory. We * check there first, and then fall back on the older naming * convention if necessary. */ if ((sig_proc = proc = c_open(*proc_path, O_RDONLY|O_DIRECTORY, 0)) < 0) { if (*++proc_path != NULL) continue; goto failure; } if (sys_fstat(proc, &proc_sb) < 0) goto failure; /* Since we are suspending threads, we cannot call any libc * functions that might acquire locks. Most notably, we cannot * call malloc(). So, we have to allocate memory on the stack, * instead. Since we do not know how much memory we need, we * make a best guess. And if we guessed incorrectly we retry on * a second iteration (by jumping to "detach_threads"). * * Unless the number of threads is increasing very rapidly, we * should never need to do so, though, as our guestimate is very * conservative. */ if (max_threads < proc_sb.st_nlink + 100) max_threads = proc_sb.st_nlink + 100; /* scope */ { pid_t pids[max_threads]; int added_entries = 0; sig_num_threads = num_threads; sig_pids = pids; for (;;) { struct kernel_dirent *entry; char buf[4096]; ssize_t nbytes = sys_getdents(proc, (struct kernel_dirent *)buf, sizeof(buf)); if (nbytes < 0) goto failure; else if (nbytes == 0) { if (added_entries) { /* Need to keep iterating over "/proc" in multiple * passes until we no longer find any more threads. This * algorithm eventually completes, when all threads have * been suspended. */ added_entries = 0; sys_lseek(proc, 0, SEEK_SET); continue; } break; } for (entry = (struct kernel_dirent *)buf; entry < (struct kernel_dirent *)&buf[nbytes]; entry = (struct kernel_dirent *)((char *)entry+entry->d_reclen)) { if (entry->d_ino != 0) { const char *ptr = entry->d_name; pid_t pid; /* Some kernels hide threads by preceding the pid with a '.' */ if (*ptr == '.') ptr++; /* If the directory is not numeric, it cannot be a * process/thread */ if (*ptr < '0' || *ptr > '9') continue; pid = local_atoi(ptr); /* Attach (and suspend) all threads */ if (pid && pid != clone_pid) { struct kernel_stat tmp_sb; char fname[entry->d_reclen + 48]; strcat(strcat(strcpy(fname, "/proc/"), entry->d_name), marker_path); /* Check if the marker is identical to the one we created */ if (sys_stat(fname, &tmp_sb) >= 0 && marker_sb.st_ino == tmp_sb.st_ino) { long i, j; /* Found one of our threads, make sure it is no duplicate */ for (i = 0; i < num_threads; i++) { /* Linear search is slow, but should not matter much for * the typically small number of threads. */ if (pids[i] == pid) { /* Found a duplicate; most likely on second pass */ goto next_entry; } } /* Check whether data structure needs growing */ if (num_threads >= max_threads) { /* Back to square one, this time with more memory */ NO_INTR(sys_close(proc)); goto detach_threads; } /* Attaching to thread suspends it */ pids[num_threads++] = pid; sig_num_threads = num_threads; if (sys_ptrace(PTRACE_ATTACH, pid, (void *)0, (void *)0) < 0) { /* If operation failed, ignore thread. Maybe it * just died? There might also be a race * condition with a concurrent core dumper or * with a debugger. In that case, we will just * make a best effort, rather than failing * entirely. */ num_threads--; sig_num_threads = num_threads; goto next_entry; } while (sys_waitpid(pid, (int *)0, __WALL) < 0) { if (errno != EINTR) { sys_ptrace_detach(pid); num_threads--; sig_num_threads = num_threads; goto next_entry; } } if (sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i++ != j || sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i != j) { /* Address spaces are distinct, even though both * processes show the "marker". This is probably * a forked child process rather than a thread. */ sys_ptrace_detach(pid); num_threads--; sig_num_threads = num_threads; } else { found_parent |= pid == ppid; added_entries++; } } } } next_entry:; } } NO_INTR(sys_close(proc)); sig_proc = proc = -1; /* If we failed to find any threads, try looking somewhere else in * /proc. Maybe, threads are reported differently on this system. */ if (num_threads > 1 || !*++proc_path) { NO_INTR(sys_close(marker)); sig_marker = marker = -1; /* If we never found the parent process, something is very wrong. * Most likely, we are running in debugger. Any attempt to operate * on the threads would be very incomplete. Let's just report an * error to the caller. */ if (!found_parent) { ResumeAllProcessThreads(num_threads, pids); sys__exit(3); } /* Now we are ready to call the callback, * which takes care of resuming the threads for us. */ args->result = args->callback(args->parameter, num_threads, pids, args->ap); args->err = errno; /* Callback should have resumed threads, but better safe than sorry */ if (ResumeAllProcessThreads(num_threads, pids)) { /* Callback forgot to resume at least one thread, report error */ args->err = EINVAL; args->result = -1; } sys__exit(0); } detach_threads: /* Resume all threads prior to retrying the operation */ ResumeAllProcessThreads(num_threads, pids); sig_pids = NULL; num_threads = 0; sig_num_threads = num_threads; max_threads += 100; } } }
GNOKII_API gn_error gn_file_phonebook_raw_parse(gn_phonebook_entry *entry, char *line) { char memory_type_char[3]; char number[GN_PHONEBOOK_NUMBER_MAX_LENGTH]; int length, o, offset = 0; gn_error error = GN_ERR_NONE; memset(entry, 0, sizeof(gn_phonebook_entry)); length = strlen(line); entry->empty = true; memory_type_char[2] = 0; GET_NEXT_TOKEN(); switch (o) { case 0: return GN_ERR_WRONGDATAFORMAT; case 1: /* empty name: this is a request to delete the entry */ break; default: break; } STORE_TOKEN(entry->name); offset += o; BUG(offset >= length); GET_NEXT_TOKEN(); switch (o) { case 0: return GN_ERR_WRONGDATAFORMAT; default: break; } STORE_TOKEN(entry->number); offset += o; BUG(offset >= length); GET_NEXT_TOKEN(); switch (o) { case 3: break; default: return GN_ERR_WRONGDATAFORMAT; } STORE_TOKEN(memory_type_char); offset += o; BUG(offset >= length); entry->memory_type = gn_str2memory_type(memory_type_char); /* We can store addressbook entries only in ME or SM (or ON on some models) */ if (entry->memory_type != GN_MT_ME && entry->memory_type != GN_MT_SM && entry->memory_type != GN_MT_ON) { return GN_ERR_INVALIDMEMORYTYPE; } BUG(offset >= length); memset(number, 0, sizeof(number)); GET_NEXT_TOKEN(); STORE_TOKEN(number); switch (o) { case 0: return GN_ERR_WRONGDATAFORMAT; case 1: entry->location = 0; break; default: entry->location = atoi(number); break; } offset += o; BUG(offset >= length); memset(number, 0, sizeof(number)); GET_NEXT_TOKEN(); STORE_TOKEN(number); switch (o) { case 0: return GN_ERR_WRONGDATAFORMAT; case 1: entry->caller_group = 0; break; default: entry->caller_group = atoi(number); break; } offset += o; entry->empty = false; for (entry->subentries_count = 0; offset < length; entry->subentries_count++) { if (entry->subentries_count == GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER) { fprintf(stderr, _("Formatting error: too many subentries\n")); error = GN_ERR_WRONGDATAFORMAT; goto endloop; } memset(number, 0, sizeof(number)); GET_NEXT_TOKEN(); STORE_TOKEN(number); switch (o) { case 0: fprintf(stderr, _("Formatting error: unknown error while reading subentry type\n")); error = GN_ERR_WRONGDATAFORMAT; goto endloop; case 1: fprintf(stderr, _("Formatting error: empty entry type\n")); entry->subentries[entry->subentries_count].entry_type = 0; break; default: entry->subentries[entry->subentries_count].entry_type = atoi(number); break; } offset += o; if (offset > length) { fprintf(stderr, _("Formatting error: subentry has only entry type field\n")); break; } memset(number, 0, sizeof(number)); GET_NEXT_TOKEN(); STORE_TOKEN(number); switch (o) { case 0: fprintf(stderr, _("Formatting error: unknown error while reading subentry number type\n")); error = GN_ERR_WRONGDATAFORMAT; goto endloop; case 1: fprintf(stderr, _("Formatting error: empty number type\n")); entry->subentries[entry->subentries_count].number_type = 0; /* Number type is required with Number entry type */ if (entry->subentries[entry->subentries_count].entry_type == GN_PHONEBOOK_ENTRY_Number) { error = GN_ERR_WRONGDATAFORMAT; goto endloop; } break; default: entry->subentries[entry->subentries_count].number_type = atoi(number); break; } offset += o; if (offset > length) { fprintf(stderr, _("Formatting error: subentry has only entry and number type fields\n")); break; } memset(number, 0, sizeof(number)); GET_NEXT_TOKEN(); STORE_TOKEN(number); switch (o) { case 0: fprintf(stderr, _("Formatting error: unknown error while reading subentry id\n")); error = GN_ERR_WRONGDATAFORMAT; goto endloop; case 1: fprintf(stderr, _("Formatting error: empty id\n")); entry->subentries[entry->subentries_count].id = 0; break; default: entry->subentries[entry->subentries_count].id = atoi(number); break; } offset += o; if (offset > length) { fprintf(stderr, _("Formatting error: subentry has only entry and number type fields\n")); break; } GET_NEXT_TOKEN(); switch (entry->subentries[entry->subentries_count].entry_type) { case GN_PHONEBOOK_ENTRY_Date: case GN_PHONEBOOK_ENTRY_Birthday: entry->subentries[entry->subentries_count].data.date.year = local_atoi(line + offset, 4); entry->subentries[entry->subentries_count].data.date.month = local_atoi(line + offset + 4, 2); entry->subentries[entry->subentries_count].data.date.day = local_atoi(line + offset + 6, 2); entry->subentries[entry->subentries_count].data.date.hour = local_atoi(line + offset + 8, 2); entry->subentries[entry->subentries_count].data.date.minute = local_atoi(line + offset + 10, 2); entry->subentries[entry->subentries_count].data.date.second = local_atoi(line + offset + 12, 2); break; case GN_PHONEBOOK_ENTRY_ExtGroup: entry->subentries[entry->subentries_count].data.id = local_atoi(line + offset, 3); break; default: STORE_TOKEN(entry->subentries[entry->subentries_count].data.number); break; } switch (o) { case 0: fprintf(stderr, _("Formatting error: unknown error while reading subentry contents\n")); error = GN_ERR_WRONGDATAFORMAT; goto endloop; case 1: fprintf(stderr, _("Formatting error: empty subentry contents\n")); break; default: break; } offset += o; } endloop: /* Fake subentry: this is to send other exports (like from 6110) to 7110 */ if (!entry->subentries_count) { entry->subentries[entry->subentries_count].entry_type = GN_PHONEBOOK_ENTRY_Number; entry->subentries[entry->subentries_count].number_type = GN_PHONEBOOK_NUMBER_General; entry->subentries[entry->subentries_count].id = 2; snprintf(entry->subentries[entry->subentries_count].data.number, sizeof(entry->subentries[entry->subentries_count].data.number), "%s", entry->number); entry->subentries_count = 1; } return error; }
int32_t main(void) { int32_t bLoop = true; uint32_t com, seg, onoff; uint8_t u8Item; char input; char text[LCD_DIGIT_NUM]=""; int32_t idx = 0, blinkfreq, ret; long long num; S_LCD_INIT lcdinit; STR_UART_T param; SYS_SetChipClockSrc((CLK_PWRCTL_HXT_EN | CLK_PWRCTL_LXT_EN), 1); // Wait HXT and LXT stable while(SYS_CheckChipClockSrc(CLK_CLKSTATUS_LXT_STB | CLK_CLKSTATUS_HXT_STB) != 0) ; /* Select UART Clock Source From 12MHz */ SYS_SelectIPClockSource_1(CLK_CLKSEL1_UART_MASK, CLK_CLKSEL1_UART_HXT); MFP_UART0_TO_PORTA(); param.u32BaudRate = 115200; param.u32cDataBits = DRVUART_DATABITS_8; param.u32cStopBits = DRVUART_STOPBITS_1; param.u32cParity = DRVUART_PARITY_NONE; param.u32cRxTriggerLevel = DRVUART_FIFO_1BYTES; param.u8TimeOut = 0; UART_Init(UART0, ¶m); /* Select LCD Clock Source From 32KHz */ SYS_SelectIPClockSource_1(CLK_CLKSEL1_LCD_MASK, CLK_CLKSEL1_LCD_LXT); /* Select LCD Clock Source From 10KHz */ //SYS_SelectIPClockSource_1(CLK_CLKSEL1_LCD_MASK, CLK_CLKSEL1_LCD_LIRC); /* Select LCD COMs, SEGs, V1 ~ V3, DH1, DH2 */ MFP_LCD_TYPEA(); /* LCD Initialize */ lcdinit.cpump_enable = true; lcdinit.internal_bias = false; lcdinit.cpump_freqdiv = LCD_CPUMP_DIV1; lcdinit.cpump_voltage = LCD_CPVOl_3V; lcdinit.bias = LCD_BIAS_THIRD; lcdinit.mux = LCD_MUX_ONE_FOURTH; lcdinit.freqdiv = LCD_FREQ_DIV64; LCD_Init(&lcdinit); while(bLoop) { idx = 0; strcpy(text, ""); // clear buffer TestItem(); u8Item = getchar(); printf("%c\n", u8Item); switch(u8Item) { case '0': { printf("Input text: "); while(1) { input = getchar(); printf("%c", input); if(input == 0xD) break; strcat( text, &input); idx++; if(idx >= LCD_ALPHABET_NUM) break; } printf("\n"); printf("%s \n", text); LCD_Write(text); break; } case '1': { printf("Input number: "); while(1) { input = getchar(); printf("%c", input); if(input == 0xD) break; strcat( text, &input); idx++; if(idx >= LCD_DIGIT_NUM) break; } printf("\n"); //num = atof(text); num = local_atoi(text); LCD_Number(num); break; } case '2': { //DrvLCD_Write("NUVOTON"); LCD_Number(8888888888888); input: printf("Input the frequency of blinking (ms): "); blinkfreq = sysGetNum(); printf("\n"); ret = LCD_BlinkFrequency(blinkfreq); if(ret == ERR_LCD_CAL_BLINK_FAIL) { printf("Over the time range and input again...\n"); goto input; } LCD_EnableInt(LCD_FRAMECOUNT_INT); LCD_EnableBlink(); printf("Any key to end Blinking display..."); getchar(); LCD_DisableBlink(); break; } case '3': printf("Pixel On/Off (1:On, 0:Off): "); onoff = sysGetNum(); printf("\n"); if(onoff>1) continue; printf("Input Com: "); com = sysGetNum(); printf("\nInput Segment: "); seg = sysGetNum(); if(onoff) LCD_EnableSegment(com, seg); else LCD_DisableSegment(com, seg); break; case '4': bLoop = false; break; default: printf("Wrong Item\n"); break; } } LCD_Disable(); return true; }