コード例 #1
0
static void wq_enqueue(struct thr_info *thr, struct T1_chain *t1)
{
	struct work *work = get_work(thr, thr->id);
	struct work_queue *wq;
	struct work_ent *we;
	int rolls = 0;

	wq = &t1->active_wq;

	while (42) {
		we = cgmalloc(sizeof(*we));

		we->work = work;
		INIT_LIST_HEAD(&we->head);

		mutex_lock(&t1->lock);
		list_add_tail(&we->head, &wq->head);
		wq->num_elems++;
		mutex_unlock(&t1->lock);

		if (wq->num_elems >= t1->num_active_chips * 2) {
			break;
		}
		if (rolls > work->drv_rolllimit) {
			work = get_work(thr, thr->id);
			continue;
		}
		work = make_clone(work);
		roll_work(work);
	}
}
コード例 #2
0
ファイル: main.c プロジェクト: EmmanuelKasper/minix-st-1.5
/*===========================================================================*
 *				main					     *
 *===========================================================================*/
PUBLIC void main()
{
/* Main routine of the memory manager. */

  int error;

  mm_init();			/* initialize memory manager tables */

  /* This is MM's main loop-  get work and do it, forever and forever. */
  while (TRUE) {
	/* Wait for message. */
	get_work();		/* wait for an MM system call */
	mp = &mproc[who];

  	/* Set some flags. */
	error = OK;
	dont_reply = FALSE;
	err_code = -999;

	/* If the call number is valid, perform the call. */
	if (mm_call < 0 || mm_call >= NCALLS)
		error = EBADCALL;
	else
		error = (*call_vec[mm_call])();

	/* Send the results back to the user to indicate completion. */
	if (dont_reply) continue;	/* no reply for EXIT and WAIT */
	if (mm_call == EXEC && error == OK) continue;
	reply(who, error, result2, res_ptr);
  }
}
コード例 #3
0
ファイル: boss-worker.c プロジェクト: flaviusone/APP
void
boss()
{
  struct q_work_struct *ptr;
  int ret,i;
  i = 0;
  /* obtain work, return when complete */
  for ( ; ; ) {
    /* allocate a work structure */
    ptr = (struct q_work_struct *) malloc (sizeof(struct q_work_struct));
    if ( ptr == NULL )
      break;
    
    /* create/obtain work and fill in the work structure */
    ret = get_work(ptr,i);
    if ( ret == 0 ) {
      free((void *)ptr);
      break;
    }

    /* queue up the work */
    if ( enqueue(&thr_queue, ptr) != 0 ) {
      fprintf(stderr, "enqueue() error\n");
      exit(-1);
    }
    i++;
  }
}
コード例 #4
0
ファイル: worker.c プロジェクト: anuragpeshne/minix
/*===========================================================================*
 *				worker_main				     *
 *===========================================================================*/
static void *worker_main(void *arg)
{
/* Worker thread main loop */
  struct worker_thread *me;

  me = (struct worker_thread *) arg;
  ASSERTW(me);

  while(TRUE) {
	get_work(me);

	/* Register ourselves in fproc table if possible */
	if (me->w_job.j_fp != NULL) {
		me->w_job.j_fp->fp_wtid = me->w_tid;
	}

	/* Carry out work */
	me->w_job.j_func(&me->w_job);

	/* Deregister if possible */
	if (me->w_job.j_fp != NULL) {
		me->w_job.j_fp->fp_wtid = invalid_thread_id;
	}

	/* Mark ourselves as done */
	me->w_job.j_func = NULL;
	me->w_job.j_fp = NULL;
  }

  return(NULL);	/* Unreachable */
}
コード例 #5
0
ファイル: MT_MAIN.C プロジェクト: daemqn/Atari_ST_Sources
/* --------------------------------- */
void init_mtext(void)
{
register int i, j;
int a, b;

scrtchp = (long)Malloc(2048L);

mtext_mlen = (long)Malloc(-1L) - 75000;
mtext_mem = (unsigned char *)Malloc(mtext_mlen);

/*printf("\033H%lx\n", mtext_mem);*/

memset(mtext_mem, 0, mtext_mlen);

pathes[0][0] = Dgetdrv();
pathes[0][1] = ':';
Dgetpath(pathes[0] + 2, 0);
strcat(pathes[0] + 2, "\\");
pathes[0][0] += 'A';

strcpy(pathes[1], pathes[0]);
strcpy(pathes[2], pathes[0]);
strcpy(pathes[3], pathes[0]);

pic_fpath[0] = pathes[0][0];
del_file[0] = font_path[0] = pathes[0][0];

for (i = 0; i < 68; txt_lineal[0][i++] = '.');
txt_lineal[0][68] = 0;

strcpy(txt_lineal[1], txt_lineal[0]);
strcpy(txt_lineal[2], txt_lineal[0]);
strcpy(txt_lineal[3], txt_lineal[0]);

strncpy(txt_linpar[0], "NPS110", 6);
strncpy(txt_linpar[1], txt_linpar[0], 6);
strncpy(txt_linpar[2], txt_linpar[0], 6);
strncpy(txt_linpar[3], txt_linpar[0], 6);

strcpy(txt_infol[0], "  Seite: 999, Zeile: 99999, Spalte: 999          Einf�gen ");
strcpy(txt_infol[1], txt_infol[0]);
strcpy(txt_infol[2], txt_infol[0]);
strcpy(txt_infol[3], txt_infol[0]);

vst_alignment(vdi_handle, 0, 3, &a, &b);
vsf_perimeter(vdi_handle, FALSE);

load_cfg();

get_work(0);
for (i = 0; i < 4; i++)
	{
	w_koor[i][0] = wx;
	w_koor[i][1] = wy;
	w_koor[i][2] = ww - (3 - i) * 10;
	w_koor[i][3] = wh - i * 10;
	}
}
コード例 #6
0
ファイル: MT_MAIN.C プロジェクト: daemqn/Atari_ST_Sources
/* ---------------------- */
void button_mesag(void)
{
get_work(w_handles[akt_id]);

if (pt_inrect(mousex, mousey, wx, wy, ww, wh))
	if (ruler_flag && mousey - wy < 16 && mousey >= wy)
		{
		if (mousex < wx + 24)
			edit_aktruler();
		else
			set_tab();
		}
	else
		set_cursor();
}
コード例 #7
0
ファイル: deviceapi.c プロジェクト: medikid/MaxSharesMiner
static
struct work *get_and_prepare_work(struct thr_info *thr)
{
	struct cgpu_info *proc = thr->cgpu;
	struct device_drv *api = proc->drv;
	struct work *work;
	
	work = get_work(thr);
	if (!work)
		return NULL;
	if (api->prepare_work && !api->prepare_work(thr, work)) {
		free_work(work);
		applog(LOG_ERR, "%"PRIpreprv": Work prepare failed, disabling!", proc->proc_repr);
		proc->deven = DEV_RECOVER_ERR;
		run_cmd(cmd_idle);
		return NULL;
	}
	return work;
}
コード例 #8
0
ファイル: grep.c プロジェクト: SuguruTakahashi/git
static void *run(void *arg)
{
	int hit = 0;
	struct grep_opt *opt = arg;

	while (1) {
		struct work_item *w = get_work();
		if (!w)
			break;

		opt->output_priv = w;
		hit |= grep_source(opt, &w->source);
		grep_source_clear_data(&w->source);
		work_done(w);
	}
	free_grep_patterns(arg);
	free(arg);

	return (void*) (intptr_t) hit;
}
コード例 #9
0
ファイル: base.cpp プロジェクト: ankitC/meld
void
base::do_loop(void)
{
   db::node *node(NULL);

   while(true) {
      while((node = get_work())) {
         do_work(node);
         finish_work(node);
      }

      assert_end_iteration();

      // cout << id << " -------- END ITERATION ---------" << endl;

      // false from end_iteration ends program
      if(!end_iteration())
         return;
   }
}
コード例 #10
0
ファイル: main.c プロジェクト: Hooman3/minix
/*===========================================================================*
 *				main                                         *
 *===========================================================================*/
int main(int argc, char **argv)
{
/* This is the main routine of this service. The main loop consists of 
 * three major activities: getting new work, processing the work, and
 * sending the reply. The loop never terminates, unless a panic occurs.
 */
  int result;                 

  /* SEF local startup. */
  env_setargs(argc, argv);
  sef_local_startup();

  /* Main loop - get work and do it, forever. */         
  while (TRUE) {              
      /* Wait for incoming message, sets 'callnr' and 'who'. */
      get_work();

      if (is_notify(callnr)) {
	      switch (_ENDPOINT_P(who_e)) {
		      case TTY_PROC_NR:
			      result = do_fkey_pressed(&m_in);
			      break;
		      default:
			      /* FIXME: error message. */
			      result = EDONTREPLY;
			      break;
	      }
      }
      else {
          printf("IS: warning, got illegal request %d from %d\n",
          	callnr, m_in.m_source);
          result = EDONTREPLY;
      }

      /* Finally send reply message, unless disabled. */
      if (result != EDONTREPLY) {
	  reply(who_e, result);
      }
  }
  return(OK);				/* shouldn't come here */
}
コード例 #11
0
ファイル: grep.c プロジェクト: Barklad/first_app
static void *run(void *arg)
{
	int hit = 0;
	struct grep_opt *opt = arg;

	while (1) {
		struct work_item *w = get_work();
		if (!w)
			break;

		if (skip_binary(opt, (const char *)w->identifier))
			continue;

		opt->output_priv = w;
		if (w->type == WORK_SHA1) {
			unsigned long sz;
			void* data = load_sha1(w->identifier, &sz, w->name);

			if (data) {
				hit |= grep_buffer(opt, w->name, data, sz);
				free(data);
			}
		} else if (w->type == WORK_FILE) {
			size_t sz;
			void* data = load_file(w->identifier, &sz);
			if (data) {
				hit |= grep_buffer(opt, w->name, data, sz);
				free(data);
			}
		} else {
			assert(0);
		}

		work_done(w);
	}
	free_grep_patterns(arg);
	free(arg);

	return (void*) (intptr_t) hit;
}
コード例 #12
0
static void *run(void *arg)
{
	int hit = 0;
	struct grep_opt *opt = arg;

	while (1) {
		struct work_item *w = get_work();
		if (!w)
			break;

		opt->output_priv = w;
		if (w->source.type == GREP_SOURCE_SUBMODULE)
			hit |= grep_submodule_launch(opt, &w->source);
		else
			hit |= grep_source(opt, &w->source);
		grep_source_clear_data(&w->source);
		work_done(w);
	}
	free_grep_patterns(arg);
	free(arg);

	return (void*) (intptr_t) hit;
}
コード例 #13
0
ファイル: host.c プロジェクト: leonardok/university
int main(void)
{
	int cmd;
	
	/* initialize window size to defult */
	window_size = DEFAULT_WINDOW_SIZE;
	
	message_to_send = NULL;
	
	/*pthread_t pthread_id[2];
	pthread_attr_t attr;*/
	
	/* 
	 * start named pipe, this is where the host will receive user commands.
	 * it will be a producer/consumer design. pipe name should be passed as
	 * command-line argument
	 */
	create_pipe(PIPE_NAME);
	int pipe = open_pipe(PIPE_NAME, O_RDONLY);

	
	/*
	 * open a socket to do the communication. packet transaction will be 
	 * simulated above a normal connection.
	 */
	if (HOST == HOST_A)
	{
		open_socket();
		send_message_to_other("Hello Client! You can start your simulation.");
		get_message_from_other();
		printf("\n\n\n");
	}
	else 
	{
		open_connection();
		get_message_from_other();
		send_message_to_other("Hi Server.");
		printf("\n\n\n");
	}


	/*
	 * once connection is stablished we can start the SIM STATE MACHINE.
	 * our state machine will start in CLOSED 
	 */
	host_state = STATE_CLOSED;
	
	host_seq_number = rand();
	
	/*
	 * at this point we need to start our threads that will exchange 
	 * messages with the other host.
	 */
	
	/* thread to construct packets */
	pthread_t pthread_id[10];
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

	pthread_create(&pthread_id[0], 
		       &attr, 
		       (void *) &send_stuff_thread,
		       (void *) NULL);
	/*
	
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	
	pthread_create(&pthread_id[0], &attr, 
		       (void *)&receive_tcp_packet_from_other, NULL);
	*/
	

	/* loop until gets work to do */
	while (TRUE)
	{
		/* 
		 * get work from console. this is the link we have with the
		 * outside world (client)
		 */
		fflush(stdout);
		cmd = get_work(pipe);

		int  read_size;
		char buf[MAX_PIPE_DATA_SIZE];
		
		switch (cmd)
		{
			case CMD_LISTEN:
				printf("got CMD_LISTEN\n");
				cmd_listen();
				break;

			case CMD_CONNECT:
				printf("got CMD_CONNECT\n");
				cmd_connect();
				break;
				
			case CMD_SEND_PKT:
				printf("got CMD_SEND_PKT\n");
				
				sleep(1);
				
				/* get message to send over */
				while ((read_size = pipe_read(pipe, buf)) < 1);
								
				message_to_send = malloc(read_size * sizeof(char));
				strncpy(buf, message_to_send, read_size);
				
				break;
				
			case CMD_CHNG_WINDOW_SIZE:				
				printf("changed window size to %d\n", window_size);
				
				break;

			case CMD_CLOSE:
				break;

			/* ACK packet */
				
			default:
				printf("did not recognize cmd!\n");
		}
			 
	}

}
コード例 #14
0
ファイル: main.c プロジェクト: Sciumo/minix
/*===========================================================================*
 *				main					     *
 *===========================================================================*/
int main(void)
{
/* This is the main program of the file system.  The main loop consists of
 * three major activities: getting new work, processing the work, and sending
 * the reply.  This loop never terminates as long as the file system runs.
 */
  int transid;
  struct job *job;

  /* SEF local startup. */
  sef_local_startup();

  printf("Started VFS: %d worker thread(s)\n", NR_WTHREADS);

  /* This is the main loop that gets work, processes it, and sends replies. */
  while (TRUE) {
	yield_all();	/* let other threads run */
	self = NULL;
	job = NULL;
	send_work();
	get_work();

	transid = TRNS_GET_ID(m_in.m_type);
	if (IS_VFS_FS_TRANSID(transid)) {
		job = worker_getjob( (thread_t) transid - VFS_TRANSID);
		if (job == NULL) {
			printf("VFS: spurious message %d from endpoint %d\n",
				m_in.m_type, m_in.m_source);
			continue;
		}
		m_in.m_type = TRNS_DEL_ID(m_in.m_type);
	}

	if (job != NULL) {
		do_fs_reply(job);
		continue;
	} else if (who_e == PM_PROC_NR) { /* Calls from PM */
		/* Special control messages from PM */
		sys_worker_start(do_pm);
		continue;
	} else if (is_notify(call_nr)) {
		/* A task notify()ed us */
		sys_worker_start(do_control_msgs);
		continue;
	} else if (who_p < 0) { /* i.e., message comes from a task */
		/* We're going to ignore this message. Tasks should
		 * send notify()s only.
		 */
		 printf("VFS: ignoring message from %d (%d)\n", who_e, call_nr);
		 continue;
	}

	/* At this point we either have results from an asynchronous device
	 * or a new system call. In both cases a new worker thread has to be
	 * started and there might not be one available from the pool. This is
	 * not a problem (requests/replies are simply queued), except when
	 * they're from an FS endpoint, because these can cause a deadlock.
	 * handle_work() takes care of the details. */
	if (IS_DEV_RS(call_nr)) {
		/* We've got results for a device request */
		handle_work(do_async_dev_result);
		continue;
	} else {
		/* Normal syscall. */
		handle_work(do_work);
	}
  }
  return(OK);				/* shouldn't come here */
}
コード例 #15
0
ファイル: driver-hashfast.c プロジェクト: uraymeiviar/cgminer
static int64_t hfa_scanwork(struct thr_info *thr)
{
    struct cgpu_info *hashfast = thr->cgpu;
    struct hashfast_info *info = hashfast->device_data;
    int64_t hashes;
    int jobs, ret;

    if (unlikely(hashfast->usbinfo.nodev)) {
        applog(LOG_WARNING, "HFA %d: device disappeared, disabling",
               hashfast->device_id);
        return -1;
    }

    if (unlikely(thr->work_restart)) {
restart:
        thr->work_restart = false;
        ret = hfa_send_frame(hashfast, HF_USB_CMD(OP_WORK_RESTART), 0, (uint8_t *)NULL, 0);
        if (unlikely(!ret)) {
            ret = hfa_reset(hashfast, info);
            if (unlikely(!ret)) {
                applog(LOG_ERR, "HFA %d: Failed to reset after write failure, disabling",
                       hashfast->device_id);
                return -1;
            }
        }
    }

    jobs = hfa_jobs(info);

    if (!jobs) {
        ret = restart_wait(thr, 100);
        if (unlikely(!ret))
            goto restart;
        jobs = hfa_jobs(info);
    }

    if (jobs) {
        applog(LOG_DEBUG, "HFA %d: Sending %d new jobs", hashfast->device_id,
               jobs);
    }

    while (jobs-- > 0) {
        struct hf_hash_usb op_hash_data;
        struct work *work;
        uint64_t intdiff;
        int i, sequence;
        uint32_t *p;

        /* This is a blocking function if there's no work */
        work = get_work(thr, thr->id);

        /* Assemble the data frame and send the OP_HASH packet */
        memcpy(op_hash_data.midstate, work->midstate, sizeof(op_hash_data.midstate));
        memcpy(op_hash_data.merkle_residual, work->data + 64, 4);
        p = (uint32_t *)(work->data + 64 + 4);
        op_hash_data.timestamp = *p++;
        op_hash_data.bits = *p++;
        op_hash_data.starting_nonce = 0;
        op_hash_data.nonce_loops = 0;
        op_hash_data.ntime_loops = 0;

        /* Set the number of leading zeroes to look for based on diff.
         * Diff 1 = 32, Diff 2 = 33, Diff 4 = 34 etc. */
        intdiff = (uint64_t)work->device_diff;
        for (i = 31; intdiff; i++, intdiff >>= 1);
        op_hash_data.search_difficulty = i;
        op_hash_data.group = 0;
        if ((sequence = info->hash_sequence_head + 1) >= info->num_sequence)
            sequence = 0;
        ret = hfa_send_frame(hashfast, OP_HASH, sequence, (uint8_t *)&op_hash_data, sizeof(op_hash_data));
        if (unlikely(!ret)) {
            ret = hfa_reset(hashfast, info);
            if (unlikely(!ret)) {
                applog(LOG_ERR, "HFA %d: Failed to reset after write failure, disabling",
                       hashfast->device_id);
                return -1;
            }
        }

        mutex_lock(&info->lock);
        info->hash_sequence_head = sequence;
        info->works[info->hash_sequence_head] = work;
        mutex_unlock(&info->lock);

        applog(LOG_DEBUG, "HFA %d: OP_HASH sequence %d search_difficulty %d work_difficulty %g",
               hashfast->device_id, info->hash_sequence_head, op_hash_data.search_difficulty, work->work_difficulty);
    }

    mutex_lock(&info->lock);
    hashes = info->hash_count;
    info->hash_count = 0;
    mutex_unlock(&info->lock);

    return hashes;
}
コード例 #16
0
ファイル: driver-hashratio.c プロジェクト: 60E/cgminer
static void hashratio_update_work(struct cgpu_info *hashratio)
{
	struct hashratio_info *info = hashratio->device_data;
	struct thr_info *thr = hashratio->thr[0];
	struct hashratio_pkg send_pkg;
	uint32_t tmp, range, start;
	struct work *work;
	struct pool *pool;

	applog(LOG_DEBUG, "hashratio: New stratum: restart: %d, update: %d",
		thr->work_restart, thr->work_update);
	thr->work_update = false;
	thr->work_restart = false;

	work = get_work(thr, thr->id); /* Make sure pool is ready */
	discard_work(work); /* Don't leak memory */

	pool = current_pool();
	if (!pool->has_stratum)
		quit(1, "hashratio: Miner Manager have to use stratum pool");
	if (pool->coinbase_len > HRTO_P_COINBASE_SIZE)
		quit(1, "hashratio: Miner Manager pool coinbase length have to less then %d", HRTO_P_COINBASE_SIZE);
	if (pool->merkles > HRTO_P_MERKLES_COUNT)
		quit(1, "hashratio: Miner Manager merkles have to less then %d", HRTO_P_MERKLES_COUNT);

	info->pool_no = pool->pool_no;

	cgtime(&info->last_stratum);
	cg_rlock(&pool->data_lock);
	info->pool_no = pool->pool_no;
	copy_pool_stratum(info, pool);
	hashratio_stratum_pkgs(hashratio, pool);
	cg_runlock(&pool->data_lock);

	/* Configure the parameter from outside */
	memset(send_pkg.data, 0, HRTO_P_DATA_LEN);

	// fan. We're not measuring temperature so set a safe but not max value
	info->fan_pwm = HRTO_PWM_MAX * 2 / 3;
	tmp = be32toh(info->fan_pwm);
	memcpy(send_pkg.data, &tmp, 4);

	// freq
	tmp = be32toh(info->default_freq);
	memcpy(send_pkg.data + 4, &tmp, 4);
	applog(LOG_DEBUG, "set freq: %d", info->default_freq);

	/* Configure the nonce2 offset and range */
	range = 0xffffffff / (total_devices + 1);
	start = range * (hashratio->device_id + 1);

	tmp = be32toh(start);
	memcpy(send_pkg.data + 8, &tmp, 4);

	tmp = be32toh(range);
	memcpy(send_pkg.data + 12, &tmp, 4);

	/* Package the data */
	hashratio_init_pkg(&send_pkg, HRTO_P_SET, 1, 1);
	hashratio_send_pkgs(hashratio, &send_pkg);
}
コード例 #17
0
ファイル: driver-avalon2.c プロジェクト: february10/appDemo
static int64_t avalon2_scanhash(struct thr_info *thr)
{
	struct avalon2_pkg send_pkg;
	struct timeval current_stratum;

	struct pool *pool;
	struct cgpu_info *avalon2 = thr->cgpu;
	struct avalon2_info *info = avalon2->device_data;

	int64_t h;
	uint32_t tmp, range, start;
	int i;

	if (thr->work_restart || thr->work_update || !info->first) {
		applog(LOG_DEBUG, "Avalon2: New stratum: restart: %d, update: %d, first: %d",
		       thr->work_restart, thr->work_update, info->first);
		thr->work_update = false;
		thr->work_restart = false;
		get_work(thr, thr->id); /* Make sure pool is ready */

		pool = current_pool();
		if (!pool->has_stratum)
			quit(1, "Avalon2: Miner Manager have to use stratum pool");
		if (pool->coinbase_len > AVA2_P_COINBASE_SIZE) {
			applog(LOG_ERR, "Avalon2: Miner Manager pool coinbase length have to less then %d", AVA2_P_COINBASE_SIZE);
			return 0;
		}
		if (pool->merkles > AVA2_P_MERKLES_COUNT) {
			applog(LOG_ERR, "Avalon2: Miner Manager merkles have to less then %d", AVA2_P_MERKLES_COUNT);
			return 0;
		}

		cgtime(&info->last_stratum);
		cg_rlock(&pool->data_lock);
		info->pool_no = pool->pool_no;
		copy_pool_stratum(pool);
		avalon2_stratum_pkgs(info->fd, pool, thr);
		cg_runlock(&pool->data_lock);

		/* Configuer the parameter from outside */
		adjust_fan(info);
		info->set_voltage = opt_avalon2_voltage_min;
		info->set_frequency = opt_avalon2_freq_min;

		/* Set the Fan, Voltage and Frequency */
		memset(send_pkg.data, 0, AVA2_P_DATA_LEN);

		tmp = be32toh(info->fan_pwm);
		memcpy(send_pkg.data, &tmp, 4);

		applog(LOG_ERR, "Avalon2: Temp max: %d, Cut off temp: %d",
		       get_current_temp_max(info), opt_avalon2_overheat);
		if (get_current_temp_max(info) >= opt_avalon2_overheat)
			tmp = encode_voltage(0);
		else
			tmp = encode_voltage(info->set_voltage);
		tmp = be32toh(tmp);
		memcpy(send_pkg.data + 4, &tmp, 4);

		tmp = be32toh(info->set_frequency);
		memcpy(send_pkg.data + 8, &tmp, 4);

		/* Configure the nonce2 offset and range */
		range = 0xffffffff / total_devices;
		start = range * avalon2->device_id;

		tmp = be32toh(start);
		memcpy(send_pkg.data + 12, &tmp, 4);

		tmp = be32toh(range);
		memcpy(send_pkg.data + 16, &tmp, 4);

		/* Package the data */
		avalon2_init_pkg(&send_pkg, AVA2_P_SET, 1, 1);
		while (avalon2_send_pkg(info->fd, &send_pkg, thr) != AVA2_SEND_OK)
			;

		if (unlikely(info->first < 2))
			info->first++;
	}

	/* Stop polling the device if there is no stratum in 3 minutes, network is down */
	cgtime(&current_stratum);
	if (tdiff(&current_stratum, &(info->last_stratum)) > (double)(3.0 * 60.0))
		return 0;

	polling(thr);

	h = 0;
	for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
		h += info->enable[i] ? (info->local_work[i] - info->hw_work[i]) : 0;
	}
	return h * 0xffffffff;
}
コード例 #18
0
/*===========================================================================*
 *				main                                         *
 *===========================================================================*/
int main(int argc, char **argv)
{
/* This is the main routine of this service. The main loop consists of 
 * three major activities: getting new work, processing the work, and
 * sending the reply. The loop never terminates, unless a panic occurs.
 */
  message m_in;
  int result;                 
  
  sef_startup();

	vector_init(&sem_list);
    Qvector_init(&waiting_list);
	stackInit(&sem_stack,5);

  /* Main loop - get work and do it, forever. */         
  while (TRUE) {              


	
      /* Wait for incoming message, sets 'callnr' and 'who'. */
    get_work(&m_in);
	//printf("SEM recieved message %d\n",callnr);
      if (is_notify(callnr)) {
          printf("SEM: warning, got illegal notify from: %d\n", m_in.m_source);
          result = EINVAL;
          goto send_reply;
      }

	int arg = m_in.m1_i1;
	switch(callnr)
	{	
		case SEM_INIT:
			//printf("Sem_init called, semaphore size 3%d.\n",arg);			
			result = sem_init(arg);			
			break;
		case SEM_UP:
			//printf("Sem_up called on semaphore %d.\n",arg);
			result = sem_up(arg);
			break;
		case SEM_DOWN:
			//printf("Sem_down called on semaphore %d. source: %d\n",arg,who_e);
			result  = sem_down(arg,m_in.m_source);
			break;
		case SEM_RELEASE:
			//printf("Sem_release called on semaphore %d.\n",arg);
			result = sem_release(arg);
			break;
		default: 
          		printf("SEMAPHORE: warning, got illegal request from %d\n", m_in.m_source);
          		result = EINVAL;
	}	



send_reply:
    	/* Finally send reply message, unless disabled. */
    	if (result != EDONTREPLY) {
        	m_in.m_type = result;  		/* build reply message */
			reply(who_e, &m_in);		/* send it away */
      }
	}
	Qvector_free(&waiting_list);
	vector_free(&sem_list);
	return(OK);				/* shouldn't come here */
}
コード例 #19
0
void master(const struct fracInfo info)
{
    int ntasks, dest, msgsize;
    struct fracData *work = malloc(sizeof(*work));
    MPI_Status status;
    int rowsTaken = 0;

    MPI_Comm_size(MPI_COMM_WORLD, &ntasks);    

    size_t size = sizeof(unsigned char) * (unsigned long)info.nCols * (unsigned long)info.nRows;
    unsigned char *fractal = (unsigned char*)malloc(size);
    if(!fractal) {
        printf("fractal allocation failed, %lu bytes\n", size);
        exit(1);
    }

    // Allocate buffer
    int membersize, emptysize, fullsize;
    int position;
    char *buffer;
    MPI_Pack_size(1, MPI_INT, MPI_COMM_WORLD, &membersize);
    emptysize = membersize;
    MPI_Pack_size(1, MPI_INT, MPI_COMM_WORLD, &membersize);
    emptysize += membersize;
    MPI_Pack_size(get_max_work_size(&info), MPI_UNSIGNED_CHAR, MPI_COMM_WORLD, &membersize);
    fullsize = emptysize + membersize;

    buffer = malloc(fullsize);    
    if(!buffer) {
        printf("buffer allocation failed, %d bytes\n",fullsize);
        exit(1);
    }

    // Send initial data
    for (dest = 1; dest < ntasks; dest++) {
        //Get next work item
        get_work(&info,&rowsTaken,work);
        
        //pack and send work       
        position = 0;
        MPI_Pack(&work->startRow,1,MPI_INT,buffer,emptysize,&position,MPI_COMM_WORLD);
        MPI_Pack(&work->nRows,1,MPI_INT,buffer,emptysize,&position,MPI_COMM_WORLD);
        MPI_Send(buffer, position, MPI_PACKED, dest, WORKTAG, MPI_COMM_WORLD);
    }

    printf("sent initial work\n");
    //Get next work item
    get_work(&info,&rowsTaken,work);
    int startRow, nRows;
    while(work->nRows) {
        // Recieve and unpack work
        MPI_Recv(buffer, fullsize, MPI_PACKED, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
        position = 0;
        MPI_Get_count(&status, MPI_PACKED, &msgsize);
        MPI_Unpack(buffer, msgsize, &position, &startRow,1,MPI_INT,MPI_COMM_WORLD);
        MPI_Unpack(buffer, msgsize, &position, &nRows,1,MPI_INT,MPI_COMM_WORLD);    
        MPI_Unpack(buffer, msgsize, &position, fractal+((unsigned long)startRow*info.nCols), nRows*info.nCols, MPI_UNSIGNED_CHAR, MPI_COMM_WORLD);

        //pack and send work       
        position = 0;
        MPI_Pack(&work->startRow,1,MPI_INT,buffer,emptysize,&position,MPI_COMM_WORLD);
        MPI_Pack(&work->nRows,1,MPI_INT,buffer,emptysize,&position,MPI_COMM_WORLD);
        MPI_Send(buffer, position, MPI_PACKED, status.MPI_SOURCE, WORKTAG, MPI_COMM_WORLD);

        //Get next work item
        get_work(&info,&rowsTaken,work);

        if(status.MPI_SOURCE==1)
            printf("%d\n",work->startRow);
    }

    // Recieve all remaining work
    for (dest = 1; dest < ntasks; dest++) {
        // Recieve and unpack work
        MPI_Recv(buffer, fullsize, MPI_PACKED, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
        position = 0;
        MPI_Get_count(&status, MPI_PACKED, &msgsize);

        MPI_Unpack(buffer, msgsize, &position, &startRow,1,MPI_INT,MPI_COMM_WORLD);
        MPI_Unpack(buffer, msgsize, &position, &nRows,1,MPI_INT,MPI_COMM_WORLD);
        // unpack pixel data
        MPI_Unpack(buffer, msgsize, &position, fractal+((unsigned long)startRow*info.nCols), nRows*info.nCols, MPI_UNSIGNED_CHAR, MPI_COMM_WORLD);

        // Kill slaves
        MPI_Send(0,0,MPI_INT,dest,DIETAG,MPI_COMM_WORLD);
    }

    free(work);
    free(buffer);

    //Save image as TIFF
    unsigned int nx = info.nCols;
    unsigned int ny = info.nRows;
    char fileName[] = "/home/pi/Mandelbrot/Mandelbrot.tiff";
    TIFF *out = TIFFOpen(fileName, "w");
    uint32 tileDim = 256;
    tsize_t tileBytes = tileDim*tileDim*sizeof(char);
    unsigned char *buf = (unsigned char *)_TIFFmalloc(tileBytes);
    char description[1024];
    snprintf(description, sizeof(description),"xStart:%f yStart:%f spacing:%f AAx:%d",info.xStart,info.yStart,info.spacing,info.AA);
    TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, description);
    TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (uint32) nx);
    TIFFSetField(out, TIFFTAG_IMAGELENGTH, (uint32) ny);
    TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
    TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1);
    TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8);
    TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
    TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
    TIFFSetField(out, TIFFTAG_TILEWIDTH, tileDim);
    TIFFSetField(out, TIFFTAG_TILELENGTH,  tileDim);
//    TIFFSetField(out, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL);
//    TIFFSetField(out, TIFFTAG_XRESOLUTION, resolution);
//    TIFFSetField(out, TIFFTAG_YRESOLUTION, resolution);
//    TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);    
    unsigned long x,y,i,j;
    unsigned long tileStart;
    // Iterate through and write tiles
    for(y=0; y<ny; y+=tileDim) {
        for(x=0; x<nx; x+=tileDim) {
            // Fill tile with fractal data
            tileStart = y*nx+x;
            for(i=0; i<tileDim; i++) {
                for(j=0; j<tileDim; j++) {
                    if(x+j < nx && y+i < ny)
                        buf[i*tileDim+j] = fractal[(y+i)*nx+(x+j)];
                    else
                        buf[i*tileDim+j] = (unsigned char)0;
                }
            }
            TIFFWriteTile(out, buf, x, y, 0, 0);
        }
    }
    
    TIFFClose(out);
    _TIFFfree(buf);
    free(fractal);
}
コード例 #20
0
ファイル: cpu-miner.c プロジェクト: btwo/cpuminer
static void *miner_thread(void *userdata)
{
	struct thr_info *mythr = userdata;
	int thr_id = mythr->id;
	uint32_t max_nonce = 0xffffff;

	/* Set worker threads to nice 19 and then preferentially to SCHED_IDLE
	 * and if that fails, then SCHED_BATCH. No need for this to be an
	 * error if it fails */
	setpriority(PRIO_PROCESS, 0, 19);
	drop_policy();

	/* Cpu affinity only makes sense if the number of threads is a multiple
	 * of the number of CPUs */
	if (!(opt_n_threads % num_processors))
		affine_to_cpu(mythr->id, mythr->id % num_processors);

	while (1) {
		struct work work __attribute__((aligned(128)));
		uint64_t hashes_done;
		struct timeval tv_start, tv_end, diff;
		uint64_t max64;
		bool rc;

		/* obtain new work from internal workio thread */
		if (unlikely(!get_work(mythr, &work))) {
			applog(LOG_ERR, "work retrieval failed, exiting "
				"mining thread %d", mythr->id);
			goto out;
		}

		hashes_done = 0;
		gettimeofday(&tv_start, NULL);

		rc = scanhash(thr_id, work.data, work.target, max_nonce, &hashes_done);

		/* record scanhash elapsed time */
		gettimeofday(&tv_end, NULL);
		timeval_subtract(&diff, &tv_end, &tv_start);

		hashmeter(thr_id, &diff, hashes_done);

		/* adjust max_nonce to meet target scan time */
		if (diff.tv_usec > 500000)
			diff.tv_sec++;
		if (diff.tv_sec > 0) {
			max64 =
			   (hashes_done / 65536 * opt_scantime) / diff.tv_sec;
			if (max64 > 0xfffffffaULL)
				max64 = 0xfffffffaULL;
			max_nonce = max64;
		}

		/* if nonce found, submit work */
		if (rc && !submit_work(mythr, &work))
			break;
	}

out:
	tq_freeze(mythr->q);

	return NULL;
}
コード例 #21
0
ファイル: MT_MAIN.C プロジェクト: daemqn/Atari_ST_Sources
/* ------------------- */
void init_rsc(void)
{
OBJECT *form;
register int i, j;
											 
rsrc_gaddr(ROOT, SONDER_Z, &form);
form[LINE3].ob_spec.free_string[1] = 0;
form[LINEA].ob_spec.free_string[31] = 0x7F;
for (i = LINE3; i <= LINEA; i++)
	for (j = 1; j < 33; j += 2)
		form[i].ob_spec.free_string[j] += 0x80;
		
*form[SOND_EDT].ob_spec.tedinfo->te_ptext = 0;

rsrc_gaddr(ROOT, SET_FONT, &form);
form[FONT_S].ob_state |= SELECTED;

rsrc_gaddr(ROOT, EINRUECK, &form);
*form[EINR_NUM].ob_spec.tedinfo->te_ptext = 0;

rsrc_gaddr(ROOT, FIND_REP, &form);
form[SR_CURSR].ob_state |= SELECTED;
form[SR_CRDWN].ob_state |= SELECTED;
*form[FIND_STR].ob_spec.tedinfo->te_ptext = 0;
*form[REPL_STR].ob_spec.tedinfo->te_ptext = 0;

rsrc_gaddr(ROOT, DISK_FMT, &form);
form[DRIVE_A].ob_state |= SELECTED;
form[NORM_FMT].ob_state |= SELECTED;
form[ONE_SIDE].ob_state |= SELECTED;

rsrc_gaddr(ROOT, PRT_MENU, &form);
form[TO_PRINT].ob_state |= SELECTED;
form[NO_INHLT].ob_state |= SELECTED;
form[NO_INDEX].ob_state |= SELECTED;
form[PRT_PICS].ob_state |= SELECTED;
form[NO_MAIL].ob_state |= SELECTED;
form[PRT_DRFT].ob_state |= SELECTED;
form[PRT_TEXT].ob_state |= SELECTED;

rsrc_gaddr(ROOT, NOTE_DIA, &form);
form[N_LOCK].ob_state |= SELECTED;
for (i = N_LINE2; i <= N_LINE7; i++)
	{
	form[i].ob_spec.tedinfo->te_ptmplt = form[N_LINE1].ob_spec.tedinfo->te_ptmplt;
	form[i].ob_spec.tedinfo->te_pvalid = form[N_LINE1].ob_spec.tedinfo->te_pvalid;
	form[i].ob_spec.tedinfo->te_txtlen = 40;
	form[i].ob_spec.tedinfo->te_tmplen = 40;
	}

rsrc_gaddr(ROOT, NEW_RULR, &form);
*form[TAB_WDTH].ob_spec.tedinfo->te_ptext = 0;

rsrc_gaddr(ROOT, TXT_INFO, &form);
form[EINZ_SWT].ob_state |= SELECTED;
form[PASS_SWT].ob_state |= SELECTED;

for (i = TI_LINE1; i <= TI_LINE9; i++)
	{
	form[i].ob_spec.tedinfo->te_ptmplt = form[TI_LINE1].ob_spec.tedinfo->te_ptmplt;
	form[i].ob_spec.tedinfo->te_pvalid = form[TI_LINE1].ob_spec.tedinfo->te_pvalid;
	form[i].ob_spec.tedinfo->te_tmplen = 40;
	form[i].ob_spec.tedinfo->te_txtlen = 40;
	}

form[TI_LINEA].ob_spec.tedinfo->te_txtlen = 34;
form[TI_BEARE].ob_spec.tedinfo->te_txtlen = 29;

rsrc_gaddr(ROOT, KOPFFUSS, &form);
for (i = 0; i < 12; i++)
	{
	form[kf_anp[i]].ob_spec.tedinfo->te_ptmplt = form[G_LFT_1].ob_spec.tedinfo->te_ptmplt;
	form[kf_anp[i]].ob_spec.tedinfo->te_pvalid = form[G_LFT_1].ob_spec.tedinfo->te_pvalid;
	form[kf_anp[i]].ob_spec.tedinfo->te_txtlen = 26;
	form[kf_anp[i]].ob_spec.tedinfo->te_tmplen = 26;
	}

rsrc_gaddr(ROOT, FLOSKEL, &form);
for (i = FLSK_L1; i <= FLSK_L5; i++)
	{
	form[i].ob_spec.tedinfo->te_ptmplt = form[FLSK_L1].ob_spec.tedinfo->te_ptmplt;
	form[i].ob_spec.tedinfo->te_pvalid = form[FLSK_L1].ob_spec.tedinfo->te_pvalid;
	form[i].ob_spec.tedinfo->te_tmplen = 40;
	form[i].ob_spec.tedinfo->te_txtlen = 40;
	}

get_work(0);
rsrc_gaddr(ROOT, BACKGRND, &back);

back[ROOT].ob_x = wx;
back[ROOT].ob_y = wy;
back[ROOT].ob_width = ww;
back[ROOT].ob_height = wh;

ww = (ww - 20) / 10;
wx += 10;
wy = wh - back[F1].ob_height - 20;
for (i = 0; i < 40; i += 4)
	{
	back[F1 + i].ob_x = wx;
	back[F1 + i].ob_y = wy;
	back[F1 + i].ob_width = ww;
	back[F1_BUT + i].ob_width = ww;
	back[F1_BUT + i].ob_type = G_BOX;
	back[F1_BUT].ob_spec.index |= 0xFF0000;
	back[F1_TXT + i].ob_width = ww;

	back[F1_TXT + i].ob_spec.tedinfo->te_ptext = f_text[((i < 36) ? i / 4 + 1 : 0)];
	wx += ww;
	}

wind_set(0, WF_NEWDESK, back, 0, 0);
full_redraw();
}
コード例 #22
0
ファイル: driver-hashfast.c プロジェクト: fgrotta/cgminer
static int64_t hfa_scanwork(struct thr_info *thr)
{
	struct cgpu_info *hashfast = thr->cgpu;
	struct hashfast_info *info = hashfast->device_data;
	int jobs, ret, cycles = 0;
	int64_t hashes;

	if (unlikely(hashfast->usbinfo.nodev)) {
		applog(LOG_WARNING, "%s %d: device disappeared, disabling",
		       hashfast->drv->name, hashfast->device_id);
		return -1;
	}

	if (unlikely(last_getwork - hashfast->last_device_valid_work > 60)) {
		applog(LOG_WARNING, "%s %d: No valid hashes for over 1 minute, attempting to reset",
		       hashfast->drv->name, hashfast->device_id);
		if (info->hash_clock_rate > HFA_CLOCK_DEFAULT) {
			info->hash_clock_rate -= 5;
			if (info->hash_clock_rate < opt_hfa_hash_clock)
				opt_hfa_hash_clock = info->hash_clock_rate;
			applog(LOG_WARNING, "%s %d: Decreasing clock speed to %d with reset",
			       hashfast->drv->name, hashfast->device_id, info->hash_clock_rate);
		}
		ret = hfa_reset(hashfast, info);
		if (!ret) {
			applog(LOG_ERR, "%s %d: Failed to reset after hash failure, disabling",
			       hashfast->drv->name, hashfast->device_id);
			return -1;
		}
		applog(LOG_NOTICE, "%s %d: Reset successful", hashfast->drv->name,
		       hashfast->device_id);
	}

	if (unlikely(thr->work_restart)) {
restart:
		info->last_restart = time(NULL);
		thr->work_restart = false;
		ret = hfa_send_frame(hashfast, HF_USB_CMD(OP_WORK_RESTART), 0, (uint8_t *)NULL, 0);
		if (unlikely(!ret)) {
			ret = hfa_reset(hashfast, info);
			if (unlikely(!ret)) {
				applog(LOG_ERR, "%s %d: Failed to reset after write failure, disabling",
				       hashfast->drv->name, hashfast->device_id);
				return -1;
			}
		}
		/* Give a full allotment of jobs after a restart, not waiting
		 * for the status update telling us how much to give. */
		jobs = info->usb_init_base.inflight_target;
	} else {
		/* Only adjust die clocks if there's no restart since two
		 * restarts back to back get ignored. */
		hfa_temp_clock(hashfast, info);
		jobs = hfa_jobs(hashfast, info);
	}

	/* Wait on restart_wait for up to 0.5 seconds or submit jobs as soon as
	 * they're required. */
	while (!jobs && ++cycles < 5) {
		ret = restart_wait(thr, 100);
		if (unlikely(!ret))
			goto restart;
		jobs = hfa_jobs(hashfast, info);
	}

	if (jobs) {
		applog(LOG_DEBUG, "%s %d: Sending %d new jobs", hashfast->drv->name, hashfast->device_id,
		       jobs);
	}

	while (jobs-- > 0) {
		struct hf_hash_usb op_hash_data;
		struct work *work;
		uint64_t intdiff;
		int i, sequence;
		uint32_t *p;

		/* This is a blocking function if there's no work */
		work = get_work(thr, thr->id);

		/* Assemble the data frame and send the OP_HASH packet */
		memcpy(op_hash_data.midstate, work->midstate, sizeof(op_hash_data.midstate));
		memcpy(op_hash_data.merkle_residual, work->data + 64, 4);
		p = (uint32_t *)(work->data + 64 + 4);
		op_hash_data.timestamp = *p++;
		op_hash_data.bits = *p++;
		op_hash_data.starting_nonce = 0;
		op_hash_data.nonce_loops = 0;
		op_hash_data.ntime_loops = 0;

		/* Set the number of leading zeroes to look for based on diff.
		 * Diff 1 = 32, Diff 2 = 33, Diff 4 = 34 etc. */
		intdiff = (uint64_t)work->device_diff;
		for (i = 31; intdiff; i++, intdiff >>= 1);
		op_hash_data.search_difficulty = i;
		op_hash_data.group = 0;
		if ((sequence = info->hash_sequence_head + 1) >= info->num_sequence)
			sequence = 0;
		ret = hfa_send_frame(hashfast, OP_HASH, sequence, (uint8_t *)&op_hash_data, sizeof(op_hash_data));
		if (unlikely(!ret)) {
			ret = hfa_reset(hashfast, info);
			if (unlikely(!ret)) {
				applog(LOG_ERR, "%s %d: Failed to reset after write failure, disabling",
				       hashfast->drv->name, hashfast->device_id);
				return -1;
			}
		}

		mutex_lock(&info->lock);
		info->hash_sequence_head = sequence;
		info->works[info->hash_sequence_head] = work;
		mutex_unlock(&info->lock);

		applog(LOG_DEBUG, "%s %d: OP_HASH sequence %d search_difficulty %d work_difficulty %g",
		       hashfast->drv->name, hashfast->device_id, info->hash_sequence_head,
		       op_hash_data.search_difficulty, work->work_difficulty);
	}

	/* Only count 2/3 of the hashes to smooth out the hashrate for cycles
	 * that have no hashes added. */
	mutex_lock(&info->lock);
	hashes = info->hash_count / 3 * 2;
	info->calc_hashes += hashes;
	info->hash_count -= hashes;
	mutex_unlock(&info->lock);

	return hashes;
}
コード例 #23
0
static void spondoolies_update_work_sp50(struct cgpu_info *cgpu)
{
    struct spond_adapter *device = cgpu->device_data;
	struct thr_info *thr = cgpu->thr[0];
    struct work *work = NULL;
    struct pool *pool = NULL;

    // setup thread flags
    SPONDLOG(LOG_DEBUG, "New stratum: restart: %d, update: %d", thr->work_restart, thr->work_update);
	thr->work_update = false;
	thr->work_restart = false;

	work = get_work(thr, thr->id); /* Make sure pool is ready */
	discard_work(work); /* Don't leak memory */

    // lets check pool job parameters
    pool = current_pool();
    if (!pool->has_stratum) {
        quit(1, "%s: Miner Manager have to use stratum pool", sp50_drv.dname);
    }
    if (pool->coinbase_len > SPOND_MAX_COINBASE_LEN) {
        SPONDLOG(LOG_ERR, "Miner Manager pool coinbase length[%d] have to less then %d",
                pool->coinbase_len,
                SPOND_MAX_COINBASE_LEN);
        return;
    }
    if (pool->merkles > SPOND_MAX_MERKLES) {
        SPONDLOG(LOG_ERR, "Miner Manager merkles have to less then %d", SPOND_MAX_MERKLES);
        return;
    }
    // need to lock driver, since we may drop all jobs
    // #########   DEVICE LOCK
    //
    pthread_mutex_lock(&device->lock);
    // lock and copy pool data
    // in our case pool_no is always same number
    // but swork.job_id changes each job
    cg_rlock(&pool->data_lock);
    copy_pool_stratum(device, pool);
    cg_runlock(&pool->data_lock);
    /*
     * fill job and send it to miner
     */
    pxgate_req_packet req_packet;
    memset(&req_packet, 0, sizeof(req_packet));
    req_packet.header.protocol_version = pxgate_PROTOCOL_VERSION;
    req_packet.header.message_type = pxgate_MESSAGE_TYPE_JOB_REQ;
    req_packet.header.message_size = sizeof(req_packet)-sizeof(req_packet.header);
    // TODO: use MACRO
    req_packet.mask = 0x01; // 0x01 = first request, 0x2 = drop old work
    if (device->drop_old_jobs) {
        req_packet.mask |= 0x02; // drop old work
        device->drop_old_jobs  = 0;
    }
    // currently we will send only one job
    fill_pxgate_request(&req_packet.req, cgpu);
    // #########   DEVICE UNLOCK
    //
    pthread_mutex_unlock(&device->lock);
    do_write(device->socket_fd, &req_packet, sizeof(req_packet));
    /*
     * read the response from miner
     */
    pxgate_gen_packet rsp_packet;
    uint32_t size = 0;
    if ((size = do_read_packet(device->socket_fd, &rsp_packet, sizeof(rsp_packet))) != sizeof(rsp_packet)) {
        quit(1, "%s: critical error, packet sent from miner is bad received size[%u] expected [%u], quiting...",
                sp50_drv.dname,
                size,
                sizeof(rsp_packet)
            );
    }
    switch (rsp_packet.header.message_type) {
        case pxgate_MESSAGE_TYPE_JOB_REQ_ACK:
            SPONDLOG(LOG_DEBUG, "pxgate_MESSAGE_TYPE_JOB_REQ_ACK");
            break;
        case pxgate_MESSAGE_TYPE_JOB_REQ_REJ:
            SPONDLOG(LOG_DEBUG, "pxgate_MESSAGE_TYPE_JOB_REQ_REJ");
            break;
        default:
            SPONDLOG(LOG_ERR, "unexpected type[%x]", rsp_packet.header.message_type);
            return;
    }
    /*
     * everything is ok, we cache the job
     */
    device->current_job_id = (device->current_job_id++) % MAX_SW_JOB_INDEX_IN_MINERGATE;
}
コード例 #24
0
/*===========================================================================*
 *				main                                         *
 *===========================================================================*/
int main(void)
{
/* This is the main routine of this service. The main loop consists of 
 * three major activities: getting new work, processing the work, and
 * sending the reply. The loop never terminates, unless a panic occurs.
 */
  message m;					/* request message */
  int ipc_status;				/* status code */
  int call_nr, who_e,who_p;			/* call number and caller */
  int result;                 			/* result to return */
  int s;

  /* SEF local startup. */
  sef_local_startup();
  
  if (OK != (s=sys_getmachine(&machine)))
	  panic("couldn't get machine info: %d", s);

  if (OK != (s=sys_getkinfo(&kinfo)))
	  panic("couldn't get kernel kinfo: %d", s);

  /* Main loop - get work and do it, forever. */         
  while (TRUE) {              

      /* Wait for request message. */
      get_work(&m, &ipc_status);
      who_e = m.m_source;
      if(rs_isokendpt(who_e, &who_p) != OK) {
          panic("message from bogus source: %d", who_e);
      }

      call_nr = m.m_type;

	//if(who_e == 11)printf("Message for SEM recieved in RS\n");

      /* Now determine what to do.  Four types of requests are expected:
       * - Heartbeat messages (notifications from registered system services)
       * - System notifications (synchronous alarm)
       * - User requests (control messages to manage system services)
       * - Ready messages (reply messages from registered services)
       */

      /* Notification messages are control messages and do not need a reply.
       * These include heartbeat messages and system notifications.
       */
      if (is_ipc_notify(ipc_status)) {
          switch (who_p) {
          case CLOCK:
	      do_period(&m);			/* check services status */
	      continue;
	  default:				/* heartbeat notification */
	      if (rproc_ptr[who_p] != NULL) {	/* mark heartbeat time */ 
		  rproc_ptr[who_p]->r_alive_tm = m.NOTIFY_TIMESTAMP;
	      } else {
		  printf("RS: warning: got unexpected notify message from %d\n",
		      m.m_source);
	      }
	  }
      }

      /* If we get this far, this is a normal request.
       * Handle the request and send a reply to the caller. 
       */
      else {
	  if (call_nr != COMMON_GETSYSINFO && 
	  	(call_nr < RS_RQ_BASE || call_nr >= RS_RQ_BASE+0x100))
	  {
		/* Ignore invalid requests. Do not try to reply. */
		printf("RS: warning: got invalid request %d from endpoint %d\n",
			call_nr, m.m_source);
		continue;
	  }

          /* Handler functions are responsible for permission checking. */
          switch(call_nr) {
          /* User requests. */
	  case RS_UP:		result = do_up(&m);		break;
          case RS_DOWN: 	result = do_down(&m); 		break;
          case RS_REFRESH: 	result = do_refresh(&m); 	break;
          case RS_RESTART: 	result = do_restart(&m); 	break;
          case RS_SHUTDOWN: 	result = do_shutdown(&m); 	break;
          case RS_UPDATE: 	result = do_update(&m); 	break;
          case RS_CLONE: 	result = do_clone(&m); 		break;
          case RS_EDIT: 	result = do_edit(&m); 		break;
          case COMMON_GETSYSINFO: 
         			result = do_getsysinfo(&m); 	break;
	  case RS_LOOKUP:	result = do_lookup(&m);		break;
	  /* Ready messages. */
	  case RS_INIT: 	result = do_init_ready(&m); 	break;
	  case RS_LU_PREPARE: 	result = do_upd_ready(&m); 	break;
          default: 
              printf("RS: warning: got unexpected request %d from %d\n",
                  m.m_type, m.m_source);
              result = EINVAL;
          }

          /* Finally send reply message, unless disabled. */
          if (result != EDONTREPLY) {
	      m.m_type = result;
              reply(who_e, NULL, &m);
          }
      }
  }
}
コード例 #25
0
ファイル: main.c プロジェクト: wieck/minix
/*===========================================================================*
 *				main                                         *
 *===========================================================================*/
int main(int argc, char *argv[])
{
    /* This is the main routine of this service. The main loop consists of
     * three major activities: getting new work, processing the work, and
     * sending the reply. The loop never terminates, unless a panic occurs.
     */
    int ind, do_reply, transid;
    message pfs_m_in;
    message pfs_m_out;

    /* SEF local startup. */
    env_setargs(argc, argv);
    sef_local_startup();

    while(!unmountdone || !exitsignaled) {
        endpoint_t src;

        do_reply = 1;
        /* Wait for request message. */
        get_work(&pfs_m_in);

        transid = TRNS_GET_ID(pfs_m_in.m_type);
        pfs_m_in.m_type = TRNS_DEL_ID(pfs_m_in.m_type);
        if (pfs_m_in.m_type == 0) {
            assert(!IS_VFS_FS_TRANSID(transid));
            pfs_m_in.m_type = transid;
            transid = 0;
        } else
            assert(IS_VFS_FS_TRANSID(transid) || transid == 0);

        src = pfs_m_in.m_source;
        caller_uid = INVAL_UID;	/* To trap errors */
        caller_gid = INVAL_GID;
        req_nr = pfs_m_in.m_type;

        if (IS_DEV_RQ(req_nr)) {
            ind = req_nr - DEV_RQ_BASE;
            if (ind < 0 || ind >= DEV_CALL_VEC_SIZE) {
                printf("pfs: bad DEV request %d\n", req_nr);
                pfs_m_out.m_type = EINVAL;
            } else {
                int result;
                result = (*dev_call_vec[ind])(&pfs_m_in, &pfs_m_out);
                if (pfs_m_out.REP_STATUS == SUSPEND ||
                        result == SUSPEND) {
                    /* Nothing to tell, so not replying */
                    do_reply = 0;
                }
            }
        } else if (IS_VFS_RQ(req_nr)) {
            ind = req_nr - VFS_BASE;
            if (ind < 0 || ind >= FS_CALL_VEC_SIZE) {
                printf("pfs: bad FS request %d\n", req_nr);
                pfs_m_out.m_type = EINVAL;
            } else {
                pfs_m_out.m_type =
                    (*fs_call_vec[ind])(&pfs_m_in, &pfs_m_out);
            }
        } else {
            printf("pfs: bad request %d\n", req_nr);
            pfs_m_out.m_type = EINVAL;
        }

        if (do_reply) {
            if (IS_VFS_RQ(req_nr) && IS_VFS_FS_TRANSID(transid)) {
                pfs_m_out.m_type = TRNS_ADD_ID(pfs_m_out.m_type,
                                               transid);
            }
            reply(src, &pfs_m_out);
        }
    }
    return(OK);
}
コード例 #26
0
ファイル: driver-avalon2.c プロジェクト: AntoninoA/cgminer
static int64_t avalon2_scanhash(struct thr_info *thr)
{
	struct avalon2_pkg send_pkg;

	struct pool *pool;
	struct cgpu_info *avalon2 = thr->cgpu;
	struct avalon2_info *info = avalon2->device_data;

	int64_t h;
	uint32_t tmp, range, start;
	int i;

	if (thr->work_restart || thr->work_update ||
	    info->first) {
		info->new_stratum = true;
		applog(LOG_DEBUG, "Avalon2: New stratum: restart: %d, update: %d, first: %d",
		       thr->work_restart, thr->work_update, info->first);
		thr->work_update = false;
		thr->work_restart = false;
		if (unlikely(info->first))
			info->first = false;

		get_work(thr, thr->id); /* Make sure pool is ready */

		pool = current_pool();
		if (!pool->has_stratum)
			quit(1, "Avalon2: Miner Manager have to use stratum pool");
		if (pool->swork.cb_len > AVA2_P_COINBASE_SIZE)
			quit(1, "Avalon2: Miner Manager pool coinbase length have to less then %d", AVA2_P_COINBASE_SIZE);
		if (pool->swork.merkles > AVA2_P_MERKLES_COUNT)
			quit(1, "Avalon2: Miner Manager merkles have to less then %d", AVA2_P_MERKLES_COUNT);

		info->diff = (int)pool->swork.diff - 1;
		info->pool_no = pool->pool_no;

		cg_wlock(&pool->data_lock);
		avalon2_stratum_pkgs(info->fd, pool, thr);
		cg_wunlock(&pool->data_lock);

		/* Configuer the parameter from outside */
		info->fan_pwm = opt_avalon2_fan_min;
		info->set_voltage = opt_avalon2_voltage_min;
		info->set_frequency = opt_avalon2_freq_min;

		/* Set the Fan, Voltage and Frequency */
		memset(send_pkg.data, 0, AVA2_P_DATA_LEN);

		tmp = be32toh(info->fan_pwm);
		memcpy(send_pkg.data, &tmp, 4);

		tmp = encode_voltage(info->set_voltage);
		tmp = be32toh(tmp);
		memcpy(send_pkg.data + 4, &tmp, 4);

		tmp = be32toh(info->set_frequency);
		memcpy(send_pkg.data + 8, &tmp, 4);

		/* Configure the nonce2 offset and range */
		range = 0xffffffff / total_devices;
		start = range * avalon2->device_id;

		tmp = be32toh(start);
		memcpy(send_pkg.data + 12, &tmp, 4);

		tmp = be32toh(range);
		memcpy(send_pkg.data + 16, &tmp, 4);

		/* Package the data */
		avalon2_init_pkg(&send_pkg, AVA2_P_SET, 1, 1);
		while (avalon2_send_pkg(info->fd, &send_pkg, thr) != AVA2_SEND_OK)
			;
		info->new_stratum = false;
	}

	polling(thr);

	h = 0;
	for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
		h += info->local_work[i];
	}
	return h * 0xffffffff;
}
コード例 #27
0
ファイル: main.c プロジェクト: donwea/MinixWithMutex
/*===========================================================================*
 *				main					     *
 *===========================================================================*/
int main(void)
{
/* This is the main program of the file system.  The main loop consists of
 * three major activities: getting new work, processing the work, and sending
 * the reply.  This loop never terminates as long as the file system runs.
 */
  int transid;
  struct worker_thread *wp;

  /* SEF local startup. */
  sef_local_startup();

  printf("Started VFS: %d worker thread(s)\n", NR_WTHREADS);

  /* This is the main loop that gets work, processes it, and sends replies. */
  while (TRUE) {
	worker_yield();	/* let other threads run */

	send_work();

	/* The get_work() function returns TRUE if we have a new message to
	 * process. It returns FALSE if it spawned other thread activities.
	 */
	if (!get_work())
		continue;

	transid = TRNS_GET_ID(m_in.m_type);
	if (IS_VFS_FS_TRANSID(transid)) {
		wp = worker_get((thread_t) transid - VFS_TRANSID);
		if (wp == NULL || wp->w_fp == NULL) {
			printf("VFS: spurious message %d from endpoint %d\n",
				m_in.m_type, m_in.m_source);
			continue;
		}
		m_in.m_type = TRNS_DEL_ID(m_in.m_type);
		do_reply(wp);
		continue;
	} else if (who_e == PM_PROC_NR) { /* Calls from PM */
		/* Special control messages from PM */
		service_pm();
		continue;
	} else if (is_notify(call_nr)) {
		/* A task ipc_notify()ed us */
		switch (who_e) {
		case DS_PROC_NR:
			/* Start a thread to handle DS events, if no thread
			 * is pending or active for it already. DS is not
			 * supposed to issue calls to VFS or be the subject of
			 * postponed PM requests, so this should be no problem.
			 */
			if (worker_can_start(fp))
				handle_work(ds_event);
			break;
		case KERNEL:
			mthread_stacktraces();
			break;
		case CLOCK:
			/* Timer expired. Used only for select(). Check it. */
			expire_timers(m_in.m_notify.timestamp);
			break;
		default:
			printf("VFS: ignoring notification from %d\n", who_e);
		}
		continue;
	} else if (who_p < 0) { /* i.e., message comes from a task */
		/* We're going to ignore this message. Tasks should
		 * send ipc_notify()s only.
		 */
		 printf("VFS: ignoring message from %d (%d)\n", who_e, call_nr);
		 continue;
	}

	if (IS_BDEV_RS(call_nr)) {
		/* We've got results for a block device request. */
		bdev_reply();
	} else if (IS_CDEV_RS(call_nr)) {
		/* We've got results for a character device request. */
		cdev_reply();
	} else {
		/* Normal syscall. This spawns a new thread. */
		handle_work(do_work);
	}
  }
  return(OK);				/* shouldn't come here */
}
コード例 #28
0
static int64_t serial_fpga_scanwork(struct thr_info *thr)
{
	struct cgpu_info *serial_fpga;
	int fd;
	int ret;

	struct FPGA_INFO *info;

	unsigned char ob_bin[44], nonce_buf[SERIAL_READ_SIZE];
	char *ob_hex;
	uint32_t nonce;
	int64_t hash_count;
	struct timeval tv_start, tv_finish, elapsed, tv_end, diff;
	int curr_hw_errors, i, j;
	uint32_t * ob;
	ob = (uint32_t *)ob_bin;

	int count;
	double Hs, W, fullnonce;
	int read_count;
	int64_t estimate_hashes;
	uint32_t values;
	int64_t hash_count_range;

	struct work *work;

	applog(LOG_DEBUG, "serial_fpga_scanwork...");
	
	if (thr->cgpu->deven == DEV_DISABLED)
		return -1;
	

	serial_fpga = thr->cgpu;
	info = serial_fpga->device_data;
	work = get_work(thr, thr->id);
	
	if (info->device_fd == -1) {
		
		applog(LOG_INFO, "Attemping to Reopen Serial FPGA on %s", serial_fpga->device_path);
		fd = serial_open(serial_fpga->device_path, SERIAL_IO_SPEED, SERIAL_READ_TIMEOUT, false);
		if (unlikely(-1 == fd)) {
			applog(LOG_ERR, "Failed to open Serial FPGA on %s",
				   serial_fpga->device_path);
			return -1;
		}
		else
			info->device_fd = fd;
	}

	fd = info->device_fd;
	
	memset(ob_bin, 0, sizeof(ob_bin));

//  Currently, extra nonces are not supported
//
	memset((unsigned char*)work->data + 144, 0, 12);
//
//
	
	calc_midstate(work);

	memcpy(ob_bin, work->midstate, 32);			// Midstate
	memcpy(ob_bin + 32, work->data + 128, 12);	// Remaining Bytes From Block Header

	// Send Bytes To FPGA In Reverse Order
	unsigned char swap[44];
	uint32_t * sw;
	sw = (uint32_t *)swap;
	for (j=0; j<8; j++) {
		sw[j] = swab32(ob[j]);
	}
	
	memcpy(swap + 32, ob_bin + 32, 12);

	for (j=0; j<44; j++) {
		ob_bin[j] = swap[j];
	}
	
//unsigned char* b = (unsigned char*)(ob_bin);
//applog(LOG_WARNING, "swap: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", b[28],b[29],b[30],b[31],b[32],b[33],b[34],b[35],b[36],b[37],b[38],b[39],b[40],b[41],b[42],b[43]);
//applog(LOG_WARNING, "swap: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7],b[8],b[9],b[10],b[11],b[12],b[13],b[14],b[15],b[16],b[17],b[18],b[19],b[20],b[21],b[22],b[23],b[24],b[25],b[26],b[27],b[28],b[29],b[30],b[31],b[32],b[33],b[34],b[35],b[36],b[37],b[38],b[39],b[40],b[41],b[42],b[43]);

	
//#ifndef WIN32
//	tcflush(fd, TCOFLUSH);
//#endif

	// Send Data To FPGA
	ret = write(fd, ob_bin, sizeof(ob_bin));

	if (ret != sizeof(ob_bin)) {
			applog(LOG_ERR, "%s%i: Serial Send Error (ret=%d)", serial_fpga->drv->name, serial_fpga->device_id, ret);
		serial_fpga_close(thr);
		dev_error(serial_fpga, REASON_DEV_COMMS_ERROR);
		return 0;
	}

	if (opt_debug) {
		ob_hex = bin2hex(ob_bin, sizeof(ob_bin));
		applog(LOG_DEBUG, "Serial FPGA %d sent: %s",
			serial_fpga->device_id, ob_hex);
		free(ob_hex);
	}

	elapsed.tv_sec = 0;
	elapsed.tv_usec = 0;
	cgtime(&tv_start);

	applog(LOG_DEBUG, "%s%i: Begin Scan For Nonces", serial_fpga->drv->name, serial_fpga->device_id);
	while (thr && !thr->work_restart) {

		memset(nonce_buf,0,4);
	
		// Check Serial Port For 1/10 Sec For Nonce  
		ret = read(fd, nonce_buf, SERIAL_READ_SIZE);

		// Calculate Elapsed Time
		cgtime(&tv_end);
		timersub(&tv_end, &tv_start, &elapsed);


		if (ret == 0) {		// No Nonce Found
			if (elapsed.tv_sec > info->timeout) {
				applog(LOG_DEBUG, "%s%i: End Scan For Nonces - Time = %d sec", serial_fpga->drv->name, serial_fpga->device_id, elapsed.tv_sec);
				break;
			}
			continue;
		}
		else if (ret < SERIAL_READ_SIZE) {
			applog(LOG_ERR, "%s%i: Serial Read Error (ret=%d)", serial_fpga->drv->name, serial_fpga->device_id, ret);
			serial_fpga_close(thr);
			dev_error(serial_fpga, REASON_DEV_COMMS_ERROR);
			break;
		}

		memcpy((char *)&nonce, nonce_buf, SERIAL_READ_SIZE);
		
#if !defined (__BIG_ENDIAN__) && !defined(MIPSEB)
		nonce = swab32(nonce);
#endif

		curr_hw_errors = serial_fpga->hw_errors;

		applog(LOG_INFO, "%s%i: Nonce Found - %08X (%5.1fMhz)", serial_fpga->drv->name, serial_fpga->device_id, nonce, (double)(1/(info->Hs * 1000000)));
		submit_nonce(thr, work, nonce);

		// Update Hashrate
		if (serial_fpga->hw_errors == curr_hw_errors)
			info->Hs = ((double)(elapsed.tv_sec) + ((double)(elapsed.tv_usec))/((double)1000000)) / (double)nonce;

	}

	// Estimate Number Of Hashes
	hash_count = ((double)(elapsed.tv_sec) + ((double)(elapsed.tv_usec))/((double)1000000)) / info->Hs;
	
	free_work(work);
	return hash_count;
}
コード例 #29
0
ファイル: pools.cpp プロジェクト: antho281/A42TTG2
// pool switching code
bool pool_switch(int thr_id, int pooln)
{
	int prevn = cur_pooln;
	bool algo_switch = false;
	struct pool_infos *prev = &pools[cur_pooln];
	struct pool_infos* p = NULL;

	// save prev stratum connection infos (struct)
	if (prev->type & POOL_STRATUM) {
		// may not be the right moment to free,
		// to check if required on submit...
		stratum_free_job(&stratum);
		prev->stratum = stratum;
	}

	if (pooln < num_pools) {
		cur_pooln = pooln;
		p = &pools[cur_pooln];
	} else {
		applog(LOG_ERR, "Switch to inexistant pool %d!", pooln);
		return false;
	}

	// save global attributes
	prev->allow_mininginfo = allow_mininginfo;
	prev->allow_gbt = allow_gbt;
	prev->check_dups = check_dups;

	pthread_mutex_lock(&stratum_work_lock);

	free(rpc_user); rpc_user = strdup(p->user);
	free(rpc_pass); rpc_pass = strdup(p->pass);
	free(rpc_url);  rpc_url = strdup(p->url);

	short_url = p->short_url; // just a pointer, no alloc

	opt_scantime = p->scantime;
	opt_max_diff = p->max_diff;
	opt_max_rate = p->max_rate;
	opt_shares_limit = p->shares_limit;
	opt_time_limit = p->time_limit;

	want_stratum = have_stratum = (p->type & POOL_STRATUM) != 0;

	// yiimp stats reporting
	opt_stratum_stats = (strstr(p->pass, "stats") != NULL) || (strcmp(p->user, "benchmark") == 0);

	pthread_mutex_unlock(&stratum_work_lock);

	// algo "blind" switch without free, not proper
	// todo: barrier required to free algo resources
	if (p->algo != (int) opt_algo) {

		if (opt_algo != ALGO_AUTO) {

			algo_switch = true;

			pthread_mutex_lock(&stats_lock);
			for (int n=0; n<opt_n_threads; n++)
				thr_hashrates[n] = 0.;
			stats_purge_all();
			if (check_dups)
				hashlog_purge_all();
			pthread_mutex_unlock(&stats_lock);
		}

		opt_algo = (enum sha_algos) p->algo;
	}

	if (prevn != cur_pooln) {

		pool_switch_count++;
		net_diff = 0;
		g_work_time = 0;
		g_work.data[0] = 0;
		pool_is_switching = true;
		stratum_need_reset = true;
		// used to get the pool uptime
		firstwork_time = time(NULL);
		restart_threads();
		// reset wait states
		for (int n=0; n<opt_n_threads; n++)
			conditional_state[n] = false;

		// restore flags
		allow_gbt = p->allow_gbt;
		allow_mininginfo = p->allow_mininginfo;
		check_dups = p->check_dups;

		if (want_stratum) {

			// temporary... until stratum code cleanup
			stratum = p->stratum;
			stratum.pooln = cur_pooln;

			// unlock the stratum thread
			tq_push(thr_info[stratum_thr_id].q, strdup(rpc_url));
			applog(LOG_BLUE, "Switch to stratum pool %d: %s", cur_pooln,
				strlen(p->name) ? p->name : p->short_url);
		} else {
			applog(LOG_BLUE, "Switch to pool %d: %s", cur_pooln,
				strlen(p->name) ? p->name : p->short_url);
		}

		// will unlock the longpoll thread on /LP url receive
		want_longpoll = (p->type & POOL_LONGPOLL) || !(p->type & POOL_STRATUM);
		if (want_longpoll) {
			pthread_mutex_lock(&stratum_work_lock);
			// will issue a lp_url request to unlock the longpoll thread
			have_longpoll = false;
			get_work(&thr_info[0], &g_work);
			pthread_mutex_unlock(&stratum_work_lock);
		}

	}
	return true;
}
コード例 #30
0
ファイル: cpu-miner.c プロジェクト: prcarter/cpuminer
static void *miner_thread(void *thr_id_int)
{
	int thr_id = (unsigned long) thr_id_int;
	int failures = 0;
	uint32_t max_nonce = 0xffffff, max_nonce2;
	CURL *curl;

	if (opt_randomize) {
		srandom(time(0));
	}

	curl = curl_easy_init();
	if (!curl) {
		fprintf(stderr, "CURL initialization failed\n");
		return NULL;
	}

	while (1) {
		struct work work __attribute__((aligned(128)));
		unsigned long hashes_done;
		struct timeval tv_start, tv_end, diff;
		bool rc;

		/* obtain new work from bitcoin */
		if (!get_work(curl, &work)) {
			fprintf(stderr, "json_rpc_call failed, ");

			if ((opt_retries >= 0) && (++failures > opt_retries)) {
				fprintf(stderr, "terminating thread\n");
				return NULL;	/* exit thread */
			}

			/* pause, then restart work loop */
			fprintf(stderr, "retry after %d seconds\n",
				opt_fail_pause);
			sleep(opt_fail_pause);
			continue;
		}

		if (!validate_midstate(work.data, work.midstate)) {
			printf("SERVER PROBLEM: work.midstate does not equal SHA256 state after first 64-byte chunk\n");
		}

		hashes_done = 0;
		gettimeofday(&tv_start, NULL);

		if (opt_randomize) {
			max_nonce2 = max_nonce*(1.0 + (double)random()/(RAND_MAX+1.0) - 0.5);
		} else {
			max_nonce2 = max_nonce;
		}

		/* scan nonces for a proof-of-work hash */
		switch (opt_algo) {
		case ALGO_C:
			rc = scanhash_c(work.midstate, work.data + 64,
				        work.hash1, work.hash, work.target,
					max_nonce2, &hashes_done);
			break;

#ifdef WANT_SSE2_4WAY
		case ALGO_4WAY: {
			unsigned int rc4 =
				ScanHash_4WaySSE2(work.midstate, work.data + 64,
						  work.hash1, work.hash,
						  work.target,
						  max_nonce2, &hashes_done);
			rc = (rc4 == -1) ? false : true;
			}
			break;
#endif

#ifdef WANT_VIA_PADLOCK
		case ALGO_VIA:
			rc = scanhash_via(work.data, work.target,
					  max_nonce2, &hashes_done);
			break;
#endif
		case ALGO_CRYPTOPP:
			rc = scanhash_cryptopp(work.midstate, work.data + 64,
				        work.hash1, work.hash, work.target,
					max_nonce2, &hashes_done);
			break;

#ifdef WANT_CRYPTOPP_ASM32
		case ALGO_CRYPTOPP_ASM32:
			rc = scanhash_asm32(work.midstate, work.data + 64,
				        work.hash1, work.hash, work.target,
					max_nonce2, &hashes_done);
			break;
#endif

		default:
			/* should never happen */
			return NULL;
		}

		/* record scanhash elapsed time */
		gettimeofday(&tv_end, NULL);
		timeval_subtract(&diff, &tv_end, &tv_start);

		hashmeter(thr_id, &diff, hashes_done);

		/* adjust max_nonce to meet target scan time */
		if (diff.tv_sec > (opt_scantime * 2))
			max_nonce /= 2;			/* large decrease */
		else if ((diff.tv_sec > opt_scantime) &&
			 (max_nonce > 1500000))
			max_nonce -= 1000000;		/* small decrease */
		else if ((diff.tv_sec < opt_scantime) &&
			 (max_nonce < 0xffffec76))
			max_nonce += 100000;		/* small increase */

		/* if nonce found, submit work */
		if (rc)
			submit_work(curl, &work);

		failures = 0;
	}

	curl_easy_cleanup(curl);

	return NULL;
}