Beispiel #1
0
DataBuffer::~DataBuffer()
{
	test_memory();
	if (this->size)
	{
		DEBUG("Doing nothing!\n");
		delete[] this->data;
	}
	test_memory();
}
Beispiel #2
0
/*
 * Perform a memory test on external main memory.
 */
void
verify_external_mem(int loops, unsigned int addr_bus_size, unsigned int size)
{
    void initialize_system();
    int i;
    int databus_errors = 0;
    int addrbus_errors = 0;
    int memory_errors = 0;

    initialize_system();

    for (i = 1; i <= loops; i++) {
        printf("\nTesting external memory: iteration %d of %d\n",
               i, loops);
        if (test_data_bus(EXTERNAL_MEM_BASE) < 0)
            databus_errors++;

        if (test_addr_bus(EXTERNAL_MEM_BASE, addr_bus_size) < 0)
            addrbus_errors++;

        if (test_memory(EXTERNAL_MEM_BASE, size) < 0)
            memory_errors++;
    }
    printf("Data Bus Errors = %d\n", databus_errors);
    printf("Address Bus Errors = %d\n", addrbus_errors);
    printf("Memory Errors = %d\n", memory_errors);
}
Beispiel #3
0
void		show_alloc_mem()
{

  t_header	*header_free;
  t_header	*header_alloc;
  void		*end_addr;

  end_addr = sbrk(0);
  my_putstr("\nstart addr\n");
  my_aff_header(&start_free);
  header_free = start_free.next;
  printf("\n\nheader_free %p\n", (void *)header_free);
  while (header_free != &start_free)
    {
      if (header_free->next == header_free + header_free->size)
	printf("CONTIGUE\n");
      else
	printf("PAS CONTIGUE\n");
      my_aff_header(header_free);
      header_alloc = header_free + header_free->size;
      while (header_alloc != header_free->next && (void *)header_alloc < end_addr)
	{
	  printf("FIND BLOC ALLOC\n");
	  if (test_memory(header_alloc) < 0)
	    printf("Error memory\n");
	  else
	    printf("memory OK\n");
	  my_aff_header(header_alloc);
	  header_alloc += header_alloc->size;
	}
      header_free = header_free->next;
    }
}
Beispiel #4
0
int main(int argc, char** argv)
{
  //purpose of main function- parse arguments and run max argv[1] tests or max errors argv[2] with BER of argv[3].
  //prints the message pass rate for these tests- to be interpreted by python.
  //many tests designed to run in parallel with different arguments
  srand(time(NULL));

  time_t start_time = time(NULL);

  if(argc >= 2)
  {
    if(!strcmp(argv[1],"packeting"))
    {
      //tries, length, BER, rs_t conv_constraint
      if(argc != 7)
        printf("Incorrect argument count for packeting.\n");
      else
        test_packeting(atoi(argv[2]), atoi(argv[3]), atof(argv[4]), atoi(argv[5]), atoi(argv[6]));
    }
    else if(!strcmp(argv[1], "memory"))
      test_memory();
    else if(!strcmp(argv[1], "matrices"))
      test_matrices();
    else if(!strcmp(argv[1], "bitstream"))
      test_bitstream();
    else if(!strcmp(argv[1], "convolution"))
      test_convolution();
    else if(!strcmp(argv[1], "reed_solomon"))
      test_reed_solomon();
    else if(!strcmp(argv[1], "interleaving"))
      test_interleaving();
    else if(!strcmp(argv[1], "time"))
      printf("%f\n", time_function());
    else if(!strcmp(argv[1], "sim"))
    {
      if(argc != 6)
        printf("Incorrect argument count for sim.\n");
      else
      {
        printf("%f", message_pass_rate_sim(atoi(argv[3]), atoi(argv[2]), atof(argv[4]), atoi(argv[5])));
        return 0;  //return 0 here so as not to print anything else which will prevent interpretation of piped output to float
      }
    }
    else if(!strcmp(argv[1], "interleave_with_conv"))
    {
      //test_interleave_with_conv();
    }
    else if(!strcmp(argv[1], "segmentation"))
      test_segmentation();
  }
  else
    printf("no arguments\n");

  print_memory_usage_stats();
  if(allocated() > 0)
    named_allocation_dump();
  printf("Time taken was %is\n", (int)(time(NULL) - start_time));
  return 0;

}
Beispiel #5
0
void task_powerdown_init()
{
	//Lower F_CPU
	ClockSetSource(x2MHz);
	//disable other oscilators
	OSC.CTRL = 0b00000001;

	buttons_deinit();

	uart_stop();
	_delay_ms(10);

	turnoff_subsystems();

	uart_low_speed();
	_delay_ms(10);

	DEBUG(" *** POWER DOWN INIT ***\n");

	test_memory();

	//we do not want to enter sleep
	powerdown_loop_break = false;
	powerdown_lock.Lock();

	task_timer_setup(false);

	SD_EN_OFF;

	DEBUG("Using low speed uart\n");
}
Beispiel #6
0
int main()
{
  test_print();
  test_memory();
  test_metrics();
  test_find();
  test_locate();

  fputs("All tests passed\n", stdout);

  return 0;
}
Beispiel #7
0
void Post()
{
	DEBUG("\n *** POST *** \n");

	//Print reset reason
	DEBUG("Reset reason ... ");

	if (system_rst & 0b00100000)
		DEBUG("Software ");
	else
	if (system_rst & 0b00010000)
		DEBUG("Programming ");
	else
	if (system_rst & 0b00001000)
		DEBUG("Watchdog ");
	else
	if (system_rst & 0b00000100)
		DEBUG("Brownout ");
	else
	if (system_rst & 0b00000010)
		DEBUG("External ");
	else
	if (system_rst & 0b00000001)
		DEBUG("Power On ");
	else
		DEBUG("Unknown: %02X", system_rst);

	DEBUG("\n");

	//App name
	print_fw_info();

	//Print actual time
	DEBUG("Time is ... \n");
	print_datetime(time_get_actual());

	DEBUG("Free RAM at start ... %d\n", free_ram_at_start);
	test_memory();

	char id[23];
	GetID_str(id);
	DEBUG("Device serial number ... %s\n", id);

	DEBUG("Board rev ... %u\n", (hw_revision == HW_REW_1504) ? 1504 : 1406);

	//debug info
	debug_last_dump();
}
Beispiel #8
0
void
verify_internal_mem(int loops)
{
    void initialize_system();
    int i;

    initialize_system();

    for (i = 1; i <= loops; i++) {
        printf("\nTesting internal memory: iteration %d of %d\n",
               i, loops);
        test_data_bus(DPRAM_BASE);
        test_addr_bus(DPRAM_BASE, DPRAM_SIZE);
        test_memory(DPRAM_BASE, DPRAM_SIZE);
    }

}
Beispiel #9
0
void Post()
{
	//buzzer_beep(_1sec, 0, 0, 0, 0);

	DEBUG("\n *** POST *** \n");

	//Print reset reason
	DEBUG("Reset reason ... ");

	system_rst = RST.STATUS;

	if (RST.STATUS & 0b00100000)
		DEBUG("Software ");
	else
	if (RST.STATUS & 0b00010000)
		DEBUG("Programming ");
	else
	if (RST.STATUS & 0b00001000)
		DEBUG("Watchdog ");
	else
	if (RST.STATUS & 0b00000100)
		DEBUG("Brownout ");
	else
	if (RST.STATUS & 0b00000010)
		DEBUG("External ");
	else
	if (RST.STATUS & 0b00000001)
		DEBUG("Power On ");
	else
		DEBUG("Unknown: %02X", RST.STATUS);

	RST.STATUS = 0b00111111;
	DEBUG("\n");

	//App name
	print_fw_info();

	//Print actual time
	DEBUG("Time is ... \n");
	print_datetime();

	DEBUG("Free RAM at start ... %d\n", free_ram_at_start);
	test_memory();

	DEBUG("\n");
}
Beispiel #10
0
void do_mem_stage()
{
    bool_t read = gen_mem_read();

    word_t valm = 0;

    mem_addr = gen_mem_addr();
    mem_data = ex_mem_curr->vala;
    mem_write = gen_mem_write();
    mem_test = gen_mem_test();
    dmem_error = FALSE;

    if (read && !mem_test) {
        dmem_error = dmem_error || !get_word_val(mem, mem_addr, &valm);
        if (!dmem_error)
            sim_log("\tMemory: Read 0x%x from 0x%x\n",
                    valm, mem_addr);
    }
    if (mem_write && !mem_test) {
        word_t sink;
        /* Do a read of address just to check validity */
        dmem_error = dmem_error || !get_word_val(mem, mem_addr, &sink);
        if (dmem_error)
            sim_log("\tMemory: Invalid address 0x%x\n",
                    mem_addr);
    }
    if (mem_test && read){
        mem_test_address = mem_addr;

        int ans = test_memory(mem, mem_test_address);
        valm = ans;
    }
    mem_wb_next->icode = ex_mem_curr->icode;
    mem_wb_next->ifun = ex_mem_curr->ifun;
    mem_wb_next->vale = ex_mem_curr->vale;
    mem_wb_next->valm = valm;
    mem_wb_next->deste = ex_mem_curr->deste;
    mem_wb_next->destm = ex_mem_curr->destm;
    mem_wb_next->status = gen_m_stat();
    mem_wb_next->stage_pc = ex_mem_curr->stage_pc;
}
Beispiel #11
0
int main (void)
{
    extern void test_config (void);
    extern void test_except (void);
    extern void test_hashtable (void);
    extern void test_memory (void);
    extern void test_scanner (void);
    extern void test_template (void);

#ifdef DEBUG_MALLOC
    GC_find_leak = 1;
#endif
    test_config();
    test_except();
    test_hashtable();
    test_memory();
    test_scanner();
    test_template();

#ifdef DEBUG_MALLOC
    CHECK_LEAKS();
#endif
    return 0;
}
/* callback_print_thread_state()
A default callback used by traverse_threads() if no callback was supplied by the caller.

this function prints the thread state, thread create time, and also if 
TRAVERSE_FLAG_EXTENDED then any available extended members.

this function requires cb_param to point to a DWORD containing the 
operating system version returned by GetVersion().
*/
int callback_print_thread_state( 
	void *cb_param,   // in, out, optional
	SYSTEM_PROCESS_INFORMATION *const spi,   // in
	SYSTEM_THREAD_INFORMATION *const sti,   // in, optional
	const ULONG remaining,   // in
	const DWORD flags   // in, optional
)
{
	if( !cb_param ) /* missing a pointer to the OS version */
	{
		printf( "aborting: the default callback was not passed a pointer to the OS version.\n" );
		return TRAVERSE_CALLBACK_ABORT;
	}
	
	/* print image name if there is one, or <unknown> if not */
	if( spi->ImageName.Length 
		&& spi->ImageName.Buffer 
#ifdef TRAVERSE_SUPPORT_TEST_MEMORY
		/* check if the memory pointed to is accessible */
		&& ( /* either we're not testing memory or if we are call test_memory() */
			!( flags & TRAVERSE_FLAG_TEST_MEMORY )
			|| test_memory( 
				spi->ImageName.Buffer, 
				( (size_t)spi->ImageName.Length + 1 ), 
				TEST_FLAG_READ 
			)
		)
#endif
		&& *spi->ImageName.Buffer 
	)
		printf( "%.*ls: ", 
			(int)( spi->ImageName.Length / sizeof( WCHAR ) ), 
			spi->ImageName.Buffer 
		);
	else
		printf( "<unknown>: " );
	
	/* print process' id */
	printf( "PID %Iu", (size_t)spi->UniqueProcessId );
	
	/* if the process does not contain any threads then CONTINUE.
	in this case SKIP could be used as well. 
	they both do the same thing when 0 threads.
	*/
	if( !sti ) /* sti == NULL only when process has 0 threads: ZERO_THREADS_OK */
	{
		printf( ". WARNING! This process info contains 0 threads!\n" );
		return TRAVERSE_CALLBACK_CONTINUE;
	}
	
	/* print thread's id */
	printf( ", TID %Iu ", (size_t)sti->ClientId.UniqueThread );
	
	/* print thread state */
	printf( "state %s", ThreadState_to_cstr( sti->ThreadState ) );
	
	/* MS: "Thread Wait Reason is only applicable when the thread is in the Wait state."
	http://support.microsoft.com/?kbid=837372
	*/
	if( (KTHREAD_STATE)sti->ThreadState == Waiting )
	{
		/* the threadstate is waiting. print the reason it's waiting. */
		printf( " (%s", WaitReason_to_cstr( sti->WaitReason ) );
		
		if( (KWAIT_REASON)sti->WaitReason >= MaximumWaitReason )
		{
			/* the waitreason is unknown. print its number for diagnostic purposes. */
			printf( " (%lu)", sti->WaitReason );
		}
		
		printf( ")" );
	}
	else if( (KTHREAD_STATE)sti->ThreadState >= MaximumThreadState )
	{
		/* the threadstate is unknown. print its number for diagnostic purposes. */
		printf( " (%lu)", sti->ThreadState );
	}
	
	printf( ".\n" );
	
	
	/* print the thread's CreateTime as user's local time */
	printf( "CreateTime: " );
	print_filetime_as_local( (FILETIME *)&sti->CreateTime );
	printf( "\n" );
	
	/* don't access extended members unless this flag was passed in: */
	if( ( flags & TRAVERSE_FLAG_EXTENDED ) )
	{
		SYSTEM_EXTENDED_THREAD_INFORMATION *seti = 
			(SYSTEM_EXTENDED_THREAD_INFORMATION *)sti;
		
		/* the cb_param for this callback is set in traverse_threads()
		it's a pointer to the DWORD returned by GetVersion()
		*/
		DWORD dwMajorVersion = (DWORD)( LOBYTE( LOWORD( *(DWORD *)cb_param ) ) );
		DWORD dwMinorVersion = (DWORD)( HIBYTE( LOWORD( *(DWORD *)cb_param ) ) );
		
		
		if( ( ( dwMajorVersion == 5 ) && ( dwMinorVersion >= 1 ) ) // >= XP but < Vista
			|| ( dwMajorVersion >= 6 ) // >= Vista
		) // >= XP
		{
			printf( "StackBase: 0x%p\n", seti->StackBase );
			printf( "StackLimit: 0x%p\n", seti->StackLimit );
			printf( "Win32StartAddress: 0x%p\n", seti->Win32StartAddress );
			
			if( dwMajorVersion >= 6 ) // >= Vista
				printf( "TebAddress: 0x%p\n", seti->TebAddress );
		}
		else
			printf( "Extended members are only available for XP+.\n" );
	}
	
	printf( "\n" );
	
	return TRAVERSE_CALLBACK_CONTINUE;
}
Beispiel #13
0
/*
   create an executable context using the given device,
   output configuration, and semantics.
 */
XPAPI Xpost_Context *xpost_create(const char *device,
                                  Xpost_Output_Type output_type,
                                  const void *outputptr,
                                  Xpost_Showpage_Semantics semantics,
                                  Xpost_Output_Message output_msg,
                                  Xpost_Set_Size set_size,
                                  int width,
                                  int height)
{
    Xpost_Object sd, ud;
    int ret;
    const char *outfile = NULL;
    const char *bufferin = NULL;
    char **bufferout = NULL;
    int quiet;

    switch (output_msg)
    {
        case XPOST_OUTPUT_MESSAGE_QUIET:
            quiet = 1;
            _xpost_interpreter_is_tracing = 0;
            break;
        case XPOST_OUTPUT_MESSAGE_VERBOSE:
            quiet = 0;
            _xpost_interpreter_is_tracing = 0;
            break;
        case XPOST_OUTPUT_MESSAGE_TRACING:
            quiet = 0;
            _xpost_interpreter_is_tracing = 1;
            break;
        default:
            XPOST_LOG_ERR("Wrong output message value");
            return NULL;;
    }


    switch (output_type)
    {
        case XPOST_OUTPUT_FILENAME:
            outfile = outputptr;
            break;
        case XPOST_OUTPUT_BUFFERIN:
            bufferin = outputptr;
            break;
        case XPOST_OUTPUT_BUFFEROUT:
            bufferout = (char **)outputptr;
            break;
        case XPOST_OUTPUT_DEFAULT:
            break;
    }

#if 0
    test_memory();
    if (!test_garbage_collect(xpost_interpreter_cid_init,
                              xpost_interpreter_cid_get_context,
                              xpost_interpreter_get_initializing,
                              xpost_interpreter_set_initializing,
                              xpost_interpreter_alloc_local_memory,
                              xpost_interpreter_alloc_global_memory))
        return NULL;
#endif

    nextid = 0; /*reset process counter */

    /* Allocate and initialize all interpreter data structures. */
    ret = initalldata(device);
    if (!ret)
    {
        return NULL;
    }

    /* extract systemdict and userdict for additional definitions */
    sd = xpost_stack_bottomup_fetch(xpost_ctx->lo, xpost_ctx->ds, 0);
    ud = xpost_stack_bottomup_fetch(xpost_ctx->lo, xpost_ctx->ds, 2);

    setlocalconfig(xpost_ctx, sd,
                   device, outfile, bufferin, bufferout,
                   semantics, set_size, width, height);

    if (quiet)
    {
        xpost_dict_put(xpost_ctx,
                       sd /*xpost_stack_bottomup_fetch(ctx->lo, ctx->ds, 0)*/ ,
                       xpost_name_cons(xpost_ctx, "QUIET"),
                       null);
    }

    xpost_stack_clear(xpost_ctx->lo, xpost_ctx->hold);
    xpost_interpreter_set_initializing(0);
    loadinitps(xpost_ctx);

    ret = copyudtosd(xpost_ctx, ud, sd);
    if (ret)
    {
        XPOST_LOG_ERR("%s error in copyudtosd", errorname[ret]);
        return NULL;
    }

    /* make systemdict readonly FIXME: use new access semantics */
    xpost_dict_put(xpost_ctx, sd, xpost_name_cons(xpost_ctx, "systemdict"), sd);
    xpost_object_set_access(xpost_ctx, sd, XPOST_OBJECT_TAG_ACCESS_READ_ONLY);
#if 0
    if (!xpost_stack_bottomup_replace(xpost_ctx->lo, xpost_ctx->ds, 0, xpost_object_set_access(xpost_ctx, sd, XPOST_OBJECT_TAG_ACCESS_READ_ONLY)))
    {
        XPOST_LOG_ERR("cannot replace systemdict in dict stack");
        return NULL;
    }
#endif

    xpost_interpreter_set_initializing(0);

    return xpost_ctx;
}
Beispiel #14
0
void do_memory_with_sensor() {

	if (test_memory())
		send_string("Ok - Memoria");
	else send_string("Erro - Memoria");

	while(!read_keys());

	int restart = 0;
	char button_pressed;
	for(;;) {

		send_cmd(0x1, 26);
		send_string("6 para iniciar...");

		/* Espera  botao 6 */
		while (restart == 0 && read_keys() != '6');

		send_cmd(0x1, 26);
		send_string("Grav. iniciada.");

		/* Variaveis de contagem. */
		float sum = 0, min = 5000, max = 0;
		int count = 0;
		EE241_Address initial_address = 0;

		/* Amostragem dos valores. */
		while (read_keys() != '7') {

			uint16_t tension = getDigitalTension();
			float tension_f;
			union Temperatura temp;

			/* Transforma a tensao em temperatura */
			tension_f = (float)tension * 3300/65536;
			temp.temp_as_float = (tension_f - 600)/10;

			EE241_WriteBlock(initial_address, temp.temp_as_bytes, sizeof(float));
			temp.temp_as_float = 0;
			/* Conferir resultado. */
			memset(temp.temp_as_bytes, 0, sizeof(float));
			EE241_ReadBlock(initial_address, temp.temp_as_bytes, sizeof(float));

			/* Atualiza contadores */
			sum += temp.temp_as_float;
			initial_address += sizeof(float);
			count++;

			/* Atualiza maximo e minimo */
			if (temp.temp_as_float > max)
				max = temp.temp_as_float;

			if (temp.temp_as_float < min)
				min = temp.temp_as_float;

			/* Espera 1s; */
			//wait_n_interruptions(16667);
			wait_n_interruptions(1667);			
		}

		send_cmd(0x1, 26);
		send_string("Grav. finalizada.");

		restart = 0;
		while (!restart) {

			button_pressed = read_keys();	

			if (button_pressed == '6')
				restart = 1;

			/* Media, minimo ou maximo */
			if (button_pressed == '3' || button_pressed == '4' || 
					button_pressed == '5') {

				float data_print;
				char *text;

				char buffer[6];
				memset(buffer, 0, 6);

				/* Seleciona valor a ser impresso */
				if (button_pressed == '3') {
					data_print = sum/count;
					text = "Media = ";

				} else if (button_pressed == '4') {
					data_print = max;
					text = "Max. = ";

				} else {
					data_print = min;
					text = "Min. = ";

				}

				/* Calcula parte decimal da temperatura */
				float decimal = data_print - (int) data_print;
				/* Imprime resultado com duas casas decimais. */
				sprintf(buffer, "%d.%02d", (int) data_print, (int) (decimal * 100));

				/* Manda para o LCD. */
				send_cmd(0x1, 26);
				send_string(text);
				send_string(buffer);

			}

			/* Imprimir posicoes de memoria */
			if (button_pressed == '8') {

				/* Imprime primeira posicao. */
				union Temperatura temp;
				char buffer_data[6], buffer_address[6];

				memset(buffer_data, 0, 6);
				memset(buffer_address, 0, 6);

				EE241_Address aux_address = 0x0;

				temp.temp_as_float = 0;
				memset(temp.temp_as_bytes, 0, sizeof(float));
				EE241_ReadBlock(aux_address, temp.temp_as_bytes, sizeof(float));

				float decimal = temp.temp_as_float - (int) temp.temp_as_float;
				sprintf(buffer_data, "%d.%02d", (int) temp.temp_as_float, (int) (decimal * 100));

				sprintf(buffer_address, "0x%x", aux_address);

				send_cmd(0x1, 26);

				send_string(buffer_address);
				send_string(" - ");
				send_string(buffer_data);


				/* Imprime circularmente posicoes ate # for pressionado. */
				do {

					button_pressed = read_keys();

					if (button_pressed == '*') {

						/* Avanca na memoria */
						aux_address += sizeof(float);

						if (aux_address >= initial_address)
							aux_address = 0;

						/* Le float da memoria. */
						temp.temp_as_float = 0;
						memset(temp.temp_as_bytes, 0, sizeof(float));
						EE241_ReadBlock(aux_address, temp.temp_as_bytes, sizeof(float));

						/* Controi strings para impressao. */
						float decimal = temp.temp_as_float - (int) temp.temp_as_float;
						sprintf(buffer_data, "%d.%02d", (int) temp.temp_as_float, (int) (decimal * 100));
						sprintf(buffer_address, "0x%x", aux_address);

						/* Imprime posicao atual de memoria. */
						send_cmd(0x1, 26);
						send_string(buffer_address);
						send_string(" - ");
						send_string(buffer_data);

					}

				} while (button_pressed != '#');
			}

		}
	}

}
Beispiel #15
0
/** traverse_threads()
This function is well documented in traverse_threads.txt
*/
int traverse_threads(
    int ( __cdecl *callback )(
        void *cb_param,   // in, out, optional
        SYSTEM_PROCESS_INFORMATION *const spi,   // in
        SYSTEM_THREAD_INFORMATION *const sti,   // in, optional
        const ULONG remaining,   // in
        const DWORD flags   // in, optional
    ),   // in, optional
    void *cb_param,   // in, out, optional
    void *buffer,   // in, out, optional
    size_t buffer_bcount,   // in, optional
    const DWORD flags,   // in, optional
    LONG *status   // out, optional
)
{
    /** initialization
    */
    /* only print debug information when debugging */
#define dbg_printf   if( ( flags & TRAVERSE_FLAG_DEBUG ) )printf

    /* function pointer for NtQuerySystemInformation */
    static NTSTATUS (__stdcall *NtQuerySystemInformation)(
        SYSTEM_INFORMATION_CLASS SystemInformationClass,
        PVOID SystemInformation,
        ULONG SystemInformationLength,
        PULONG ReturnLength
    );

    /* a pointer to the current spi struct */
    SYSTEM_PROCESS_INFORMATION *spi = NULL;

    /* the type of system information that will be requested */
    SYSTEM_INFORMATION_CLASS infotype = -1;

    /* the size in bytes of SYSTEM_THREAD_INFORMATION, or if TRAVERSE_FLAG_EXTENDED
    then SYSTEM_EXTENDED_THREAD_INFORMATION */
    size_t sti_bcount = 0;

    /* a pointer to temporary memory malloc'd by this process, and its size in bytes */
    void *memory = NULL;
    size_t memory_bcount = 0;

    /* the endpoint of the buffer.
    NtQuerySystemInformation() has not written at or past this point.
    */
    size_t buffer_end = 0;

    /* if the caller didn't pass in a status pointer then point to this placeholder instead */
    LONG status_placeholder = 0;

    /* to receive the buffer length in bytes needed/written by NtQuerySystemInformation() */
    ULONG retlen = 0;

    /* the version number of the operating system returned by GetVersion() */
    DWORD dwVersion = 0;

    /* error_code is the variable returned by this function */
    int error_code = TRAVERSE_ERROR_GENERAL;


    /** special sanity struct for internal use only.
    this struct is used for validation on RECYCLE calls.
    it can also be used for diagnostic purposes. if a user sends me their
    buffer I can easily RECYCLE it and see what went wrong.
    this sanity struct is not written to the user's buffer on return from a RECYCLE call.
    only on original calls (!RECYCLE) will this struct be written to the buffer.
    */
    struct
    {
        /* the recycle_verify struct holds the information that must be verified as
        the exact same on a RECYCLE call.
        This struct must be the first member of the sanity struct.
        */
        struct
        {
            /* some magic number to signify the beginning of the sanity struct.
            this must be the first member.
            */
            char magic_begin[ TRAVERSE_MAGIC_LEN ];

            /* the sizeof the sanity struct */
            DWORD sanity_size;

            /* these are the same as those parameters passed in to this function */
            void *buffer;
            size_t buffer_bcount;
        } recycle_must_verify;

        /* the rest of the sanity struct is just any variable I need available across calls,
        or for diagnostic purposes. Some of these variables might need to be verified,
        but not necessarily be exactly the same on a RECYCLE call.
        */

        /* a copy of 'flags' */
        DWORD flags;

        /* a copy of 'retlen' */
        ULONG retlen;

        /* a copy of 'error_code' */
        int error_code;

        /* a copy of '*status' */
        LONG status;

        /* a copy of 'dwVersion' */
        DWORD dwVersion;

        /* a copy of 'reserved' */
        void *reserved;

        /* some magic number to signify the end of struct.
        this must be the last member. this must also be verified.
        */
        char magic_end[ TRAVERSE_MAGIC_LEN ];
    } sanity;

    /* pointer to the start of the reserved space in buffer.
    the sanity struct will stored in the reserved space on an original call
    */
    void *reserved = NULL;

    /* the sanity struct's memory must be zeroed to make sure padding is zeroed */
    ZeroMemory( &sanity, sizeof( sanity ) );

    /* set all 'sanity.recycle_must_verify' members to prepare for sanity check */
    memcpy(
        sanity.recycle_must_verify.magic_begin,
        TRAVERSE_MAGIC_BEGIN,
        sizeof( sanity.recycle_must_verify.magic_begin )
    );
    sanity.recycle_must_verify.sanity_size = sizeof( sanity );
    sanity.recycle_must_verify.buffer = buffer;
    sanity.recycle_must_verify.buffer_bcount = buffer_bcount;



    /** test memory
    */
#ifdef TRAVERSE_SUPPORT_TEST_MEMORY
    if( ( flags & TRAVERSE_FLAG_TEST_MEMORY ) )
    {
        DWORD memtest_flags = ( TEST_FLAG_READ | TEST_FLAG_WRITE );

        if( status
                && !test_memory(
                    status,
                    sizeof( *status ),
                    memtest_flags
                )
          )
        {
            dbg_printf( "Error: inaccessible memory pointed to by status parameter.\n" );

            error_code = TRAVERSE_ERROR_PARAMETER;
            goto quit;
        }

        /* test buffer. rem testing for write overwrites two bytes in memory.
        if RECYCLE then the current buffer is for input not output.
        only test WRITE if the current buffer is for output.
        */
        if( ( flags & TRAVERSE_FLAG_RECYCLE ) ) /* buffer contains valid info, don't overwrite! */
            memtest_flags = TEST_FLAG_READ;
        else
            memtest_flags = ( TEST_FLAG_READ | TEST_FLAG_WRITE );

        if( buffer && !test_memory( buffer, buffer_bcount, memtest_flags ) )
        {
            dbg_printf( "Error: inaccessible memory pointed to by buffer parameter.\n" );

            error_code = TRAVERSE_ERROR_PARAMETER;
            goto quit;
        }
    }
#endif // TRAVERSE_SUPPORT_TEST_MEMORY



    /** more init
    */
    /* get OS version */
    dwVersion = GetVersion();

    /* determine the type of information being requested */
    if( ( flags & TRAVERSE_FLAG_EXTENDED ) )
    {
        sti_bcount = sizeof( SYSTEM_EXTENDED_THREAD_INFORMATION );
        infotype = SystemExtendedProcessInformation;
        dbg_printf( "Process info type: SystemExtendedProcessInformation\n" );
    }
    else
    {
        sti_bcount = sizeof( SYSTEM_THREAD_INFORMATION );
        infotype = SystemProcessInformation;
        dbg_printf( "Process info type: SystemProcessInformation\n" );
    }


    if( !status ) /* the caller did not specify a location to receive status. use placeholder */
        status = &status_placeholder;

    /* rem initialize after test_memory() call, which changed the pointed to memory */
    *status = -1;


    if( !NtQuerySystemInformation )
    {
        SetLastError( 0 ); // error code is evaluated on success
        *(FARPROC *)&NtQuerySystemInformation =
            (FARPROC)GetProcAddress( GetModuleHandleA( "ntdll" ), "NtQuerySystemInformation" );

        dbg_printf( "GetProcAddress() %s. GLE: %lu, NtQuerySystemInformation: 0x%p.\n",
                    ( NtQuerySystemInformation ? "success" : "error" ),
                    GetLastError(),
                    NtQuerySystemInformation
                  );

        if( !NtQuerySystemInformation )
        {
            error_code = TRAVERSE_ERROR_QUERY;
            goto quit;
        }
    }


    /*
    If there is no callback and no output buffer (either no buffer or the buffer
    is being used as input because TRAVERSE_FLAG_RECYCLE was specified), this
    function will use the default callback, callback_print_thread_state(), which
    will be called to printf each thread's state and creation time. All numbers
    will be in decimal format unless 0x prefixed.
    */
    if( !callback && ( !buffer || ( flags & TRAVERSE_FLAG_RECYCLE ) ) )
    {
        callback = callback_print_thread_state;
        cb_param = &sanity.dwVersion;
    }



    /** allocate a buffer if necessary
    */
    if( !buffer ) /* get buffer size and malloc for memory */
    {
        /* stub address must be aligned, no char */
        SYSTEM_PROCESS_INFORMATION stub;


        /* if this is a RECYCLE call a buffer should have been passed in */
        if( ( flags & TRAVERSE_FLAG_RECYCLE ) )
        {
            dbg_printf( "Error: missing input buffer (RECYCLE).\n" );

            error_code = TRAVERSE_ERROR_PARAMETER;
            goto quit;
        }


        /* pass in a stub to receive the buffer's approximate needed size */
        retlen = 0;
        dbg_printf( "Calling NtQuerySystemInformation() to get buffer size estimate.\n" );
        *status = (LONG)NtQuerySystemInformation( infotype, &stub, 1, &retlen );
        dbg_printf(
            "NtQuerySystemInformation() status: 0x%08X retlen: %lu\n\n",
            (unsigned)*status,
            retlen
        );

        /* the smaller the length returned by NtQuerySystemInformation() the
        less doubling it will help. here check against a minimum size.
        this might be unnecessary.
        */
        if( retlen < 1048576UL )
            retlen = 1048576UL;

        /* retlen is a rough estimate, in bytes, of the amount of memory needed.
        the actual amount of memory needed depends on the number of threads
        and processes at exactly the time the function is called.
        double the size of the length to make sure there's enough space.
        */
        memory_bcount = retlen * 2;
        if( !memory_bcount )
        {
            dbg_printf( "Error: can't determine memory size. retlen: %lu\n", retlen );

            error_code = TRAVERSE_ERROR_MEMORY;
            goto quit;
        }


        dbg_printf( "Calling malloc( %Iu )\n", memory_bcount );
        memory = malloc( memory_bcount );
        if( !memory )
        {
            dbg_printf( "Error: malloc() failed.\n" );

            error_code = TRAVERSE_ERROR_MEMORY;
            goto quit;
        }

        /* use the temporary memory as the buffer */
        buffer = memory;
        buffer_bcount = memory_bcount;
    }

    /* make sure there's space to allow for sanity struct contents at the end of the buffer */
    if( buffer_bcount <= sizeof( sanity ) )
    {
        dbg_printf( "Error: buffer_bcount is too small. buffer_bcount: %Iu\n", buffer_bcount );

        error_code = TRAVERSE_ERROR_PARAMETER;
        goto quit;
    }

    /* reserve space for sanity struct by decreasing the available size in bytes of buffer */
    buffer_bcount -= sizeof( sanity );
    reserved = (void *)( (size_t)buffer + buffer_bcount );



    /** if this is a RECYCLE call there's already an array of
    SYSTEM_PROCESS_INFORMATION structs in the buffer.
    */
    if( ( flags & TRAVERSE_FLAG_RECYCLE ) ) /* buffer is used for input */
    {
        dbg_printf( "Sanity checking buffer (RECYCLE).\n" );

        /* if the buffer is valid it should contain its own copy of
        'sanity.recycle_must_verify', and its bytes should match this call's
        'sanity.recycle_must_verify' exactly.
        it would be incorrect to cast and access individual members because
        the location in the buffer holding the struct may not be aligned.
        */
        if( memcmp(
                    reserved, /* buffer's recycle_must_verify data */
                    &sanity.recycle_must_verify, /* our recycle_must_verify data */
                    sizeof( sanity.recycle_must_verify )
                )
          ) /* the memory does not match, sanity check failed */
        {
            dbg_printf( "Error: Sanity check failed. Memory doesn't match.\n" );

            error_code = TRAVERSE_ERROR_PARAMETER;
            goto quit;
        }

        /* the buffer contains valid data from a prior call, import the entire sanity struct
        */
        memcpy( &sanity, reserved, sizeof( sanity ) );

        /* do some more error checking */
        if( !sanity.retlen || ( sanity.retlen > buffer_bcount ) )
        {
            dbg_printf(
                "Error: Sanity check failed. sanity.retlen is out of bounds: %lu\n",
                sanity.retlen
            );

            error_code = TRAVERSE_ERROR_PARAMETER;
            goto quit;
        }

        if( ( ( flags ^ sanity.flags ) & TRAVERSE_FLAG_EXTENDED ) )
        {   /* EXTENDED flag differs from the original call. error */
            dbg_printf( "Error: Sanity check failed. EXTENDED flag differs from original call.\n" );

            error_code = TRAVERSE_ERROR_PARAMETER;
            goto quit;
        }

        if( memcmp( TRAVERSE_MAGIC_END, sanity.magic_end, sizeof( sanity.magic_end ) ) )
        {   /* missing end magic. maybe the original call didn't exit successfully */
            dbg_printf(
                "Error: Sanity check failed. End magic incorrect. sanity.error_code: %d\n",
                sanity.error_code
            );

            error_code = TRAVERSE_ERROR_PARAMETER;
            goto quit;
        }

        /* restore the variables needed from the original call */
        retlen = sanity.retlen;
        *status = sanity.status;

        dbg_printf( "Sanity check passed (RECYCLE). retlen: %lu\n", retlen );
    }
    /** else this is an original call (!RECYCLE) so call NtQuerySystemInformation()
    to get an array of SYSTEM_PROCESS_INFORMATION structs
    */
    else
    {
        retlen = 0;
        dbg_printf( "Calling NtQuerySystemInformation() to get process info.\n" );
        *status = (LONG)NtQuerySystemInformation(
                      infotype,
                      buffer,
                      buffer_bcount,
                      &retlen
                  );
        dbg_printf(
            "NtQuerySystemInformation() status: 0x%08X retlen: %lu\n\n",
            (unsigned)*status,
            retlen
        );

        /* check for STATUS_DATATYPE_MISALIGNMENT failure */
        if( *status == (LONG)0x80000002L )
        {
            dbg_printf( "Error: STATUS_DATATYPE_MISALIGNMENT\n" );
            dbg_printf( "buffer: %Iu\n", (size_t)buffer );

            error_code = TRAVERSE_ERROR_ALIGNMENT;
            goto quit;
        }

        /* check for STATUS_INFO_LENGTH_MISMATCH failure */
        if( ( retlen > buffer_bcount ) || ( *status == (LONG)0xC0000004L ) )
        {
            dbg_printf( "Error: the buffer is too small.\n" );
            dbg_printf(
                "status: 0x%08X, buffer_bcount: %Iu, retlen: %lu\n",
                (unsigned)*status,
                buffer_bcount,
                retlen
            );

            error_code = TRAVERSE_ERROR_BUFFER_TOO_SMALL;
            goto quit;
        }

        /* check for some other status code. it would not be safe to continue */
        if( *status || ( retlen < sizeof( SYSTEM_PROCESS_INFORMATION ) ) )
        {
            dbg_printf( "Error: NtQuerySystemInformation() failed.\n" );
            dbg_printf( "status: 0x%08X\n", (unsigned)*status );

            error_code = TRAVERSE_ERROR_QUERY;
            goto quit;
        }
    }



    /** main loop.
    traverse the SYSTEM_THREAD_INFORMATION struct array in each
    SYSTEM_PROCESS_INFORMATION struct.
    */
    /* point to the first SYSTEM_PROCESS_INFORMATION struct */
    spi = (SYSTEM_PROCESS_INFORMATION *)buffer;

    /* the endpoint address of the array of SYSTEM_PROCESS_INFORMATION structs */
    buffer_end = (size_t)buffer + retlen;

    for( ;; )
    {
        /** initialization
        */
        /* the endpoint address of the currently pointed to SYSTEM_PROCESS_INFORMATION struct */
        size_t spi_end =
            ( spi->NextEntryOffset ? ( (size_t)spi + spi->NextEntryOffset ) : buffer_end );

        /* how many bytes are needed to hold the reported size of the
        SYSTEM_THREAD_INFORMATION struct array in this spi
        */
        unsigned __int64 threads_bcount =
            (unsigned __int64)(ULONG)spi->NumberOfThreads * sti_bcount;

        /* how many SYSTEM_THREAD_INFORMATION structs are in the currently pointed to
        SYSTEM_PROCESS_INFORMATION struct (spi)
        */
        ULONG threads_ecount = 0; // calculated after error checks

        /* the endpoint address of the array of SYSTEM_THREAD_INFORMATION structs
        in the currently pointed to SYSTEM_PROCESS_INFORMATION struct (spi)
        */
        size_t threads_end = (size_t)( (size_t)&spi->Threads + threads_bcount );



        /** check for calculation errors
        */
        dbg_printf( "============================================\n" );

        /* this would only happen in the case of garbage data: */
        if( ( threads_end < (size_t)buffer )
                || ( spi_end < (size_t)buffer )
                || ( threads_end < (size_t)&spi->Threads )
                || ( spi_end < (size_t)&spi->Threads )
          )
        {
            dbg_printf( "Error: Definite garbage data, quitting...\n" );

            error_code = TRAVERSE_ERROR_CALCULATION;
            goto quit;
        }

        /* check if fewer accessible threads than reported */
        if( ( threads_end > buffer_end )
                || ( threads_end > spi_end )
                || ( spi_end > buffer_end )
          )
        {
            if( ( flags & TRAVERSE_FLAG_DEBUG ) )
            {
                printf( "-\n" );
                printf( "Error: process info may contain fewer thread structs than reported.\n" );

                printf( "All numbers not prefixed with 0x are in decimal format.\n" );

                if( ( flags & TRAVERSE_FLAG_EXTENDED ) )
                    printf( "TRAVERSE_FLAG_EXTENDED is set.\n" );

                printf( "buffer: %Iu\n", (size_t)buffer );
                printf( "buffer_end: %Iu\n", buffer_end );
                printf( "spi: %Iu\n", (size_t)spi );
                printf( "spi_end: %Iu\n", spi_end );
                printf( "threads_end: %Iu\n", threads_end );

                printf( "spi->NumberOfThreads: %lu\n", spi->NumberOfThreads );
                printf( "sti_bcount: %Iu\n", sti_bcount );
                printf(
                    "bytes needed(%lu*%Iu): %I64u\n",
                    spi->NumberOfThreads,
                    sti_bcount,
                    threads_bcount
                );

                printf( "( &spi->Threads ): %Iu\n", (size_t)&spi->Threads );
                printf(
                    "}} calculated thread struct array endpoint (%Iu+%I64u): %Iu\n\n",
                    (size_t)&spi->Threads,
                    threads_bcount,
                    threads_end
                );

                printf( "spi struct address: %Iu\n", (size_t)spi );
                printf( "array of spi structs endpoint: %Iu\n", buffer_end );
                printf( "spi->NextEntryOffset: %lu\n", spi->NextEntryOffset );
                if( spi->NextEntryOffset )
                {
                    printf(
                        "}} calculated process struct endpoint (%Iu+%lu): %Iu\n",
                        (size_t)spi,
                        spi->NextEntryOffset,
                        ( (size_t)spi + (size_t)spi->NextEntryOffset )
                    );
                }
                else
                {
                    printf( "This is reportedly the last process struct in the array.\n" );
                    printf(
                        "}} calculated process struct endpoint (array endpoint): %Iu\n",
                        buffer_end
                    );
                }

                printf( "-\n" );
            }

            /* if fewer accessible threads there is either a bug in this
            program or NtQuerySystemInformation reported incorrectly?
            quit unless IGNORE_CALCULATION_ERRORS was specified.
            */
            if( !( flags & TRAVERSE_FLAG_IGNORE_CALCULATION_ERRORS ) )
            {
                if( ( flags & TRAVERSE_FLAG_DEBUG ) )
                    printf( "Error: Calculation Error, quitting...\n" );

                error_code = TRAVERSE_ERROR_CALCULATION;
                goto quit;
            }


            /** since IGNORE_CALCULATION_ERRORS was specified,
            attempt to recover by adjusting the endpoints so they aren't out-of-bounds
            */
            if( spi_end > buffer_end )
                spi_end = buffer_end;

            if( threads_end > spi_end )
                threads_end = spi_end;

            if( threads_end < (size_t)&spi->Threads )
            {
                dbg_printf( "Error: Definite garbage data, quitting...\n" );

                error_code = TRAVERSE_ERROR_CALCULATION;
                goto quit;
            }

            dbg_printf( "recovered. spi_end: %Iu, threads_end: %Iu\n", spi_end, threads_end );
            dbg_printf( "-\n\n" );
        }



        /** print ImageName.Buffer (process' name) and info if accessible
        */
        dbg_printf( "UniqueProcessId: %Iu\n", (size_t)spi->UniqueProcessId );
        dbg_printf( "NumberOfThreads: %lu\n", spi->NumberOfThreads );
        dbg_printf( "ImageName.Length: %hu\n", spi->ImageName.Length );
        dbg_printf( "Checking for image name...\n" );

        if( !spi->ImageName.Buffer )
        {
            dbg_printf( "ImageName.Buffer: <ImageName.Buffer == 0>\n" );
        }
        else if( !spi->ImageName.Length )
        {
            dbg_printf( "ImageName.Buffer: <ImageName.Length == 0>\n" );
        }
        else if( ( (size_t)spi->ImageName.Buffer < threads_end )
                 || ( ( (size_t)spi->ImageName.Buffer + spi->ImageName.Length ) > spi_end )
               ) /* ImageName.Buffer does not point to memory in the current process info (spi) */
        {
            if( ( flags & TRAVERSE_FLAG_DEBUG ) )
            {
                printf( "ImageName.Buffer: <out of range: address 0x%0*IX, bytes: %Iu>\n",
                        (int)( sizeof( size_t ) * 2 ),
                        (size_t)spi->ImageName.Buffer,
                        ( (size_t)spi->ImageName.Length + 1 )
                      );
                printf( "Warning: ImageName.Buffer is out of process info memory range!\n" );
                printf( "All numbers not prefixed with 0x are in decimal format.\n" );
                printf( "spi->ImageName.Buffer: 0x%0*IX (%Iu)\n",
                        (int)( sizeof( size_t ) * 2 ),
                        (size_t)spi->ImageName.Buffer,
                        (size_t)spi->ImageName.Buffer
                      );
                printf( "spi->ImageName.Length: %hu\n", spi->ImageName.Length );
                printf( "threads_end: %Iu\n", threads_end );
                printf( "spi: %Iu\n", (size_t)spi );
                printf( "spi_end: %Iu\n", spi_end );
                printf( "buffer: %Iu\n", (size_t)buffer );
                printf( "buffer_end: %Iu\n", buffer_end );
            }

            if( !( flags & TRAVERSE_FLAG_IGNORE_CALCULATION_ERRORS ) )
            {
                dbg_printf( "Error: Calculation Error, quitting...\n" );

                error_code = TRAVERSE_ERROR_CALCULATION;
                goto quit;
            }
        }
        else
        {
            /* position of terminating null in ImageName.Buffer */
            unsigned epos = spi->ImageName.Length / sizeof( WCHAR );

            /* warn if there's no terminating null */
            if( spi->ImageName.Buffer[ epos ] )
                dbg_printf( "Warning: <ImageName.Buffer[ %hu ] != 0>\n", epos );

            dbg_printf( "ImageName.Buffer: %.*ls\n", (int)epos, spi->ImageName.Buffer );
        }



        /** calculate how many elements in this process' SYSTEM_THREAD_INFORMATION
        array, then compare to the process' member NumberOfThreads.
        */
        threads_ecount =
            (ULONG)( ( threads_end - (size_t)&spi->Threads ) / sti_bcount );

        if( threads_ecount != spi->NumberOfThreads )
        {
            if( ( flags & TRAVERSE_FLAG_DEBUG ) )
            {
                printf( "Error: threads_ecount != spi->NumberOfThreads\n" );
                printf( "All numbers not prefixed with 0x are in decimal format.\n" );
                printf( "sti_bcount: %Iu\n", sti_bcount );
                printf( "( &spi->Threads ): %Iu\n", (size_t)&spi->Threads );
                printf( "threads_end: %Iu\n", threads_end );
                printf( "threads_ecount: %lu\n", threads_ecount );
                printf( "spi->NumberOfThreads: %lu\n", spi->NumberOfThreads );
                printf(
                    "}} calculated thread count ((%Iu-%Iu)/%Iu): %lu\n",
                    threads_end,
                    (size_t)&spi->Threads,
                    sti_bcount,
                    threads_ecount
                );
            }

            if( !( flags & TRAVERSE_FLAG_IGNORE_CALCULATION_ERRORS ) )
            {
                dbg_printf( "Error: Calculation Error, quitting...\n" );

                error_code = TRAVERSE_ERROR_CALCULATION;
                goto quit;
            }

            /* TRAVERSE_FLAG_IGNORE_CALCULATION_ERRORS is specified */

            dbg_printf(
                "Warning: threads_ecount (%lu) != spi->NumberOfThreads (%lu)\n",
                threads_ecount,
                spi->NumberOfThreads
            );

            /* if the calculated count is bigger than the reported count then recover */
            if( threads_ecount > spi->NumberOfThreads )
            {
                threads_ecount = spi->NumberOfThreads;
                dbg_printf( "recovered. " );
            }
            dbg_printf( "using threads_ecount: %lu\n", threads_ecount );
        }



        /** callback if there are threads to be processed, or zero threads is ok
        */
        if( callback
                && ( threads_ecount || ( flags & TRAVERSE_FLAG_ZERO_THREADS_OK ) )
          )
        {
            /* a pointer to the current thread info struct. cast size_t for pointer arithmetic */
            SYSTEM_THREAD_INFORMATION *sti = NULL;

            /* how many threads in this spi have not yet been processed */
            ULONG remaining = 0;

            if( threads_ecount ) /* there are thread info structs to be processed */
            {
                sti = (SYSTEM_THREAD_INFORMATION *)&spi->Threads;
                remaining = threads_ecount - 1;
            }

            for( ;; ) /* for each thread info in the current spi */
            {
                /* callback return code */
                int ret;


                if( ( flags & TRAVERSE_FLAG_DEBUG ) )
                {
                    printf(
                        ">>>Calling callback function on process id %Iu, thread id ",
                        (size_t)spi->UniqueProcessId
                    );

                    if( sti )
                        printf( "%Iu.", (size_t)sti->ClientId.UniqueThread );
                    else
                        printf( "(null)." );

                    printf( "\n" );
                }

                ret = callback(
                          cb_param, /* the cb_param that was passed in to traverse_threads()*/
                          spi, /* the current process info struct */
                          sti, /* the current thread info struct */
                          remaining, /* how many threads in this spi have not yet been processed */
                          flags /* the flags that were passed in to traverse_threads() */
                      );

                if( ret == TRAVERSE_CALLBACK_SKIP ) /* do not process spi's remaining threads */
                {
                    dbg_printf(
                        "<<<Callback function returned: skip process' remaining threads.\n"
                    );

                    break;
                }
                else if( ret != TRAVERSE_CALLBACK_CONTINUE ) /* some other problem. quit */
                {
                    dbg_printf(
                        "<<<Callback function returned: abort immediately. ret: %d\n",
                        ret
                    );

                    error_code = TRAVERSE_ERROR_CALLBACK;
                    goto quit;
                }

                dbg_printf( "<<<Callback returned normally.\n\n" );


                if( !remaining ) /* no more threads in this spi */
                    break;

                --remaining;
                sti = (SYSTEM_THREAD_INFORMATION *)( (size_t)sti + sti_bcount );
            }
        }

        /* break if there are no more spi structs to process */
        if( !spi->NextEntryOffset || spi_end == buffer_end )
            break;

        /* the endpoint of the current spi struct is a pointer to the next spi struct in the array
        */
        spi = (SYSTEM_PROCESS_INFORMATION *)spi_end;
    } /** loop to process the next spi */


    error_code = TRAVERSE_SUCCESS;


quit:
    dbg_printf( "============================================\n\n" );

    /* if memory isn't null then temporary memory was allocated for buffer
    ( ie no buffer was passed in )
    */
    if( memory )
    {
        free( memory );
        memory = NULL;
        buffer = NULL;
    }

    /* else if there was a buffer passed in by the caller and this is an
    original call (ie not a RECYCLE) and reserved space is available then
    write the sanity struct to the buffer.
    */
    if( buffer && reserved && !( flags & TRAVERSE_FLAG_RECYCLE ) )
    {
        const char *magic_end_str = NULL;

        /* if this original call wasn't a (partial) success then invalidate the magic end.
        the buffer will not be usable for a future RECYCLE call.
        */
        if( ( error_code != TRAVERSE_SUCCESS ) && ( error_code != TRAVERSE_ERROR_CALLBACK ) )
            magic_end_str = TRAVERSE_MAGIC_BAD;
        else // buffer is ok
            magic_end_str = TRAVERSE_MAGIC_END;

        memcpy( sanity.magic_end, magic_end_str, sizeof( sanity.magic_end ) );

        /* all the variables to keep track of */
        sanity.flags = flags;
        sanity.retlen = retlen;
        sanity.error_code = error_code;
        sanity.status = *status;
        sanity.dwVersion = dwVersion;
        sanity.reserved = reserved;

        /* write the sanity struct to the end of the buffer in the location reserved earlier */
        memcpy(
            reserved, /* location of reserved space */
            &sanity, /* address of sanity struct */
            sizeof( sanity ) /* size of sanity struct == size of reserved space */
        );
    }

    return error_code;
}
Beispiel #16
0
int do_work(ZWay zway) {
	print_help();

	char cmd, cc_cmd, holder_root;
	ZWBYTE dev, inst, cc, cc_val, nconv;
	char data_path[256];
	char cmd_buffer[256];

	ZWBOOL was_idle = FALSE;

	ZWBOOL basic_level_attached = FALSE;

	int skip = 0;
	int running = TRUE;

	int level = 0;

	/*    while(1){
	 digitalWrite(LED1,1);
	 delay(500);
	 digitalWrite(LED1,0);
	 delay(500);
	 }*/
	while (running) {
		/*    	printf("\n\n\n");
		 zdata_acquire_lock(ZDataRoot(zway));
		 level = get_data(zway, zway_find_device_instance_cc_data(zway, '2', '0', 32, 'level'));
		 zdata_release_lock(ZDataRoot(zway));*/

		/*
		 zdata_acquire_lock(ZDataRoot(zway));
		 level = get_data(zway, zway_find_device_data(zway, '1', 'level'));
		 zdata_release_lock(ZDataRoot(zway));
		 */

		printf("data :::::::    %d", int_val2);

		//zdata_add_callback(zway_find_device_instance_cc_data(zway,1,0,32,"mylevel"),[ZDataChangeCallback] callback, FALSE,[void*]arg);

		printf("\nLOG,while1\n");

		if (!zway_is_running(zway)) //this is almost can not be execute
				{
			running = FALSE;
			break;
		}

		printf("\nLOG,while2\n");
		if (!zway_is_idle(zway)) //maybe wait for
				{
			printf("\nLOG, sleep\n");
			sleep_ms(10);
			continue;
		}
		skip = 0;

		/*      printf("\nLOG,while3\n");
		 if (!basic_level_attached)
		 {
		 printf("\nLOG,basic level start\n");

		 ZDataHolder basic_level_holder;
		 zdata_acquire_lock(ZDataRoot(zway));

		 basic_level_holder = zway_find_device_instance_cc_data(zway, 8, 0, 0x20, "mylevel");
		 //   basic_level_holder = zway_find_device_instance_cc_data(zway, 8, 0, 0x26, "level");
		 if (basic_level_holder)
		 {
		 printf("\nLOG,basic level holder\n");

		 basic_level_attached = (zdata_add_callback(basic_level_holder, (ZDataChangeCallback) print_basic_holder, FALSE, NULL) == NoError);
		 if (basic_level_attached){

		 zway_log(zway, Debug, ZSTR("Basic.data.mylevel holder handler attached to device 8 instance 0"));
		 printf("\nLOG,basic level attatched\n");
		 }

		 }
		 zdata_release_lock(ZDataRoot(zway));

		 }*/

		printf("\nLOG,while4\n");
		if (!basic_level_attached) {
			printf("\nLOG,basic level start\n");

			ZDataHolder basic_level_holder;
			zdata_acquire_lock(ZDataRoot(zway));

			//   basic_level_holder = zway_find_device_instance_cc_data(zway, 8, 0, 0x20, "mylevel");
			basic_level_holder = zway_find_device_instance_cc_data(zway, 2, 0,
					32, "level");
			if (basic_level_holder) {
				printf("\nLOG,basic level holder\n");

				basic_level_attached = (zdata_add_callback(basic_level_holder,
						(ZDataChangeCallback) print_basic_holder, FALSE, NULL)
						== NoError);
				if (basic_level_attached) {

					zway_log(zway, Debug,
							ZSTR(
									"Basic.data.mylevel holder handler attached to device 8 instance 0"));
					printf("\nLOG,basic level attatched\n");

					pthread_create(&pthread, NULL, observer_function, NULL);

					pthread_detach(pthread);
				}
			}
			zdata_release_lock(ZDataRoot(zway));

		}

		printf("> ");
		fgets(cmd_buffer, 255, stdin);
		was_idle = FALSE;

		nconv = sscanf(cmd_buffer, "%c %*s", &cmd);
		printf("nconv : %hhd", &nconv);
		if (nconv > 0) {
			switch (cmd) {
			case 'h':
				print_help();
				break;

			case 'd':
				nconv = sscanf(cmd_buffer, "%c %c", &cmd, &holder_root);
				if (nconv > 1) {
					switch (holder_root) {
					case 'r':
						nconv = sscanf(cmd_buffer, "%c %c %s", &cmd,
								&holder_root, data_path);
						if (nconv >= 2) {
							if (nconv == 2) {
								data_path[0] = '.';
								data_path[1] = '\0';
							}
							zdata_acquire_lock(ZDataRoot(zway));
							dump_data(zway,
									zway_find_controller_data(zway, data_path));
							zdata_release_lock(ZDataRoot(zway));
						}
						break;

					case 'd':
						nconv = sscanf(cmd_buffer, "%c %c %hhd %s", &cmd,
								&holder_root, &dev, data_path);
						if (nconv >= 3) {
							if (nconv == 3) {
								data_path[0] = '.';
								data_path[1] = '\0';
							}
							zdata_acquire_lock(ZDataRoot(zway));
							dump_data(zway,
									zway_find_device_data(zway, dev,
											data_path));
							zdata_release_lock(ZDataRoot(zway));
						}
						break;
					case 'i':
						nconv = sscanf(cmd_buffer, "%c %c %hhd %hhd %s", &cmd,
								&holder_root, &dev, &inst, data_path);
						if (nconv >= 4) {
							if (nconv == 4) {
								data_path[0] = '.';
								data_path[1] = '\0';
							}
							zdata_acquire_lock(ZDataRoot(zway));
							dump_data(zway,
									zway_find_device_instance_data(zway, dev,
											inst, data_path));
							zdata_release_lock(ZDataRoot(zway));
						}
						break;
					case 'c':
						nconv = sscanf(cmd_buffer, "%c %c %hhd %hhd %hhd %s",
								&cmd, &holder_root, &dev, &inst, &cc,
								data_path);
						if (nconv >= 5) {
							if (nconv == 5) {
								data_path[0] = '.';
								data_path[1] = '\0';
							}
							zdata_acquire_lock(ZDataRoot(zway));
							dump_data(zway,
									zway_find_device_instance_cc_data(zway, dev,
											inst, cc, data_path));
							zdata_release_lock(ZDataRoot(zway));
						}
						break;
					}
				}
				break;

			case 's':
				nconv = sscanf(cmd_buffer, "%c %hhd %hhd %hhd %c %hhd", &cmd,
						&dev, &inst, &cc, &cc_cmd, &cc_val);

				printf("nconv : %hhd \n", &nconv);

				/*

				 if (nconv == 6 && cmd == 's' && cc == 0x20 && cc_cmd == 's')
				 {
				 printf("nconv2 : %hhd \n",&nconv);
				 printf("if gogo111111111111111111111111111111111111111111111111111111111111111111\n");
				 zdata_acquire_lock(ZDataRoot(zway));
				 zway_cc_switch_multilevel_set(zway, dev, inst, cc_val, 0x01 ,NULL ,NULL,0);
				 zdata_release_lock(ZDataRoot(zway));
				 }
				 else if (nconv == 5 && cmd == 's' && cc == 0x20 && cc_cmd == 'g')
				 {
				 printf("elseif gogo\n");
				 zdata_acquire_lock(ZDataRoot(zway));
				 zway_cc_switch_multilevel_get(zway, dev, inst,NULL,NULL,0);
				 zdata_release_lock(ZDataRoot(zway));
				 }

				 */

				if (nconv == 6 && cmd == 's' && cc == 0x20 && cc_cmd == 's') {
					printf("nconv2 : %hhd \n", &nconv);
					printf(
							"if gogo111111111111111111111111111111111111111111111111111111111111111111\n");
					zdata_acquire_lock(ZDataRoot(zway));
					zway_cc_basic_set(zway, dev, inst, cc_val, NULL, NULL,
							NULL);
					zdata_release_lock(ZDataRoot(zway));

				} else if (nconv == 5 && cmd == 's' && cc == 0x20
						&& cc_cmd == 'g') {
					printf("elseif gogo\n");
					zdata_acquire_lock(ZDataRoot(zway));
					zway_cc_basic_get(zway, dev, inst, NULL, NULL, NULL);
					zdata_release_lock(ZDataRoot(zway));
				} else if (nconv == 6 && cmd == 's' && cc == 0x26
						&& cc_cmd == 's') {
					printf("nconv2 : %hhd \n", &nconv);
					printf(
							"if gogo333333333333333333333333333333333333333333333333333333333\n");
					zdata_acquire_lock(ZDataRoot(zway));
					zway_cc_switch_multilevel_set(zway, dev, inst, cc_val, 0x01,
							NULL, NULL, 0);
					zdata_release_lock(ZDataRoot(zway));
				}

				break;

			case 'n':
				nconv = sscanf(cmd_buffer, "%c %hhd", &cmd, &dev);

				if (nconv == 2)
					zway_fc_request_node_information(zway, dev, NULL, NULL,
							NULL);
				break;

			case 'm':
				test_memory(zway);
				break;

			case 'a':
				zway_fc_add_node_to_network(zway, TRUE, TRUE, NULL, NULL, NULL);
				break;
			case 'A':
				zway_fc_add_node_to_network(zway, FALSE, TRUE, NULL, NULL,
						NULL);
				break;

			case 'e':
				zway_fc_remove_node_from_network(zway, TRUE, TRUE, NULL, NULL,
						NULL);
				break;

			case 'x':
				running = FALSE;
				break;

			case 'S':
				test_save(zway);
				break;

			case 'R':
				test_restore(zway);
				break;
			case 'q':
				//	digitalWrite(LED1, 1);
				break;
			case 'w':
				//	digitalWrite(LED1, 0);
				break;

			case 'l':
				nconv = sscanf(cmd_buffer, "%c %hhd %hhd", &cmd, &dev, &inst);
				switch (nconv) {
				case 1: {
					ZWDevicesList list = zway_devices_list(zway);
					if (list != NULL) {
						int i = 0;
						printf("Devices list: ");
						while (list[i]) {
							printf("%i ", list[i]);
							i++;
						}
						zway_devices_list_free(list);
						printf("\n");
					} else
						printf("Error happened requesting devices list\n");
				}
					break;

				case 2: {
					ZWInstancesList list = zway_instances_list(zway, dev);
					if (list != NULL) {
						int i = 0;
						printf("Instances list for device %i: ", dev);
						while (list[i]) {
							printf("%i ", list[i]);
							i++;
						}
						zway_instances_list_free(list);
						printf("\n");
					} else
						printf("Error happened requesting instances list\n");
				}
					break;

				case 3: {
					ZWCommandClassesList list = zway_command_classes_list(zway,
							dev, inst);
					if (list != NULL) {
						int i = 0;
						printf(
								"Command Classes list for device %i instance %i: ",
								dev, inst);
						while (list[i]) {
							printf("%02x ", list[i]);
							i++;
						}
						zway_command_classes_list_free(list);
						printf("\n");
					} else
						printf(
								"Error happened requesting command classes list\n");
				}
					break;
				}
				break;
			}
		}
	}

	return 0;
}
Beispiel #17
0
int main(void)
{
    int disk;
    int stage2ImageNumber;
    int status;


    /* remove the pending reset again */
    writel(0xFFFFFFFF, GPIO_B_CLR_OE);
    writel((readl(SYS_CTRL_GPIO_TERSEL_CTRL1) & ~0x4),
           SYS_CTRL_GPIO_TERSEL_CTRL1);
    writel((readl(SYS_CTRL_GPIO_SECSEL_CTRL1) & ~0x4),
           SYS_CTRL_GPIO_SECSEL_CTRL1);
    writel((readl(SYS_CTRL_GPIO_PRIMSEL_CTRL1) & ~0x4),
           SYS_CTRL_GPIO_PRIMSEL_CTRL1);

    ddr_control = 0;
    stage2_size = 120000;
    stage2ImageNumber = 0;
    stage2_ram_addr = 0x48d00000;
    header_length = (u32 *) (stage2_ram_addr - 8);
    header_crc = (u32 *) (stage2_ram_addr - 4);

    // Base the UART divider on the system clock
    int baud_divisor_x16 = NOMINAL_SYSCLK / 115200;
    if (readl(CONFIG_REGISTER) != readl(START_OF_ROM)) {
        /* use FPGA system clock speed. */
        baud_divisor_x16 = FPGA_CLK / 115200;
    } else {
        /* use ASIC nominal system clock. */
        baud_divisor_x16 = NOMINAL_SYSCLK / 115200;
    }
    start_timer();
    set_pll();

    // Initialise the UART to be used by the CoPro for debug messages
    debug_uart = (NS16550_t) UART_2_BASE;
    init_NS16550(debug_uart, baud_divisor_x16);


    putc_NS16550(debug_uart, 'N');

    init_ddr();
    putc_NS16550(debug_uart, 'A');

    test_memory(stage2_ram_addr);       /* sends 'S' after writing */
    putc_NS16550(debug_uart, 'O');

    /* no need to re-initialise SATA controller just load details. */
    if ((readl(BOOT_STATUS0) == 0x01)
        || (readl(BOOT_VERSION) == 0x36303030ul)) {
        disk = 0;
    } else {
        disk = 1;
    }

    do {
        init_sata_hw();

        status =
            run_sata(stage2_disk_sector[stage2ImageNumber], stage2_size,
                     (u32 *) header_length, disk);

        if (status == 0) {
            putstr(debug_uart, "X");
        } else {
            putstr(debug_uart, "x");
        }

        if (stage2ImageNumber > 0) {
            putstr(debug_uart, "R");
        } else {
            putstr(debug_uart, "_");
        }

        putc_NS16550(debug_uart, (char) ('0' + (char) disk));

        /* try the backup stage2 on this disk first (first tim round, at least we know
           it is working to some extent, go to next disk if this wraps round */
        if (++stage2ImageNumber >= numStage2Images) {
            stage2ImageNumber = 0;
            if (++disk > 1) {
                disk = 0;
            }
        }

    } while (!
             (status != 0 && *header_length
              && *header_length <= stage2_size
              && *header_crc == crc32(0, (unsigned char *) stage2_ram_addr,
                                      *header_length)));

    putstr(debug_uart, "800\r\n");

    putstr(debug_uart, build_string);

    putc_NS16550(debug_uart, '\r');
    putc_NS16550(debug_uart, '\n');


#if (OVERCLOCK_PLL)
    putstr(debug_uart, "Overclocking with ");
    putstr(debug_uart, ultohex(OVERCLOCK_PLL));
    putc_NS16550(debug_uart, ' ');
#endif                          // OVERCLOCK_PLL


    ((void (*)(void)) stage2_ram_addr) ();

    return 0;
}