コード例 #1
0
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;
    }
  }
}
コード例 #2
0
ファイル: gsm-filetypes.c プロジェクト: pkot/gnokii
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;
}
コード例 #3
0
ファイル: main.c プロジェクト: bimopraks/tinythread
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, &param);

	/* 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;

}