Пример #1
0
/**
 * Creates new threads
 * @param s
 */
void threads_create( struct state * s )
{
  int i;
  size_t sz;
  struct threads * t;
  pthread_attr_t attr;

  if ( !( t = s->thread_mngr ) )
    return;

  t->running = 1;
  t->finished = 0;

  // Initialise the mutex which will sync the job queue
  if ( pthread_mutex_init( &t->queue_lock, NULL ) )
  {
    state_error( s, "Cannot create queue mutex" );
  }

  // Initialise the mutex which will be used with the signal
  if ( pthread_mutex_init( &t->exit_lock, NULL ) )
  {
    state_error( s, "Cannot create exit mutex" );
  }

  // Initialse the mutex which will guard the data_primes array
  if ( pthread_mutex_init( &t->save_lock, NULL ) )
  {
    state_error( s, "Cannot create save mutex" );
  }

  // Initialise the mutex which will guard the output array
  if ( pthread_rwlock_init( &t->write_lock, NULL ) )
  {
    state_error( s, "Cannot create write mutex" );
  }

  // Initialise the cond variable which will signal
  // the main thread when we're done
  if ( pthread_cond_init( &t->exit_cond, NULL) )
  {
    state_error( s, "Cannot create exit signal" );
  }

  // Allocate storage space for the thread handles
  sz = sizeof( pthread_t ) * s->thread_count;
  assert( t->threads = (pthread_t*)malloc( sz ) );
  memset( t->threads, 0, sz );

  // Create joinable threads with 2Mb stack
  pthread_attr_init( &attr );
  pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
  pthread_attr_setstacksize( &attr, 2 << 20 );

  for ( i = 0; i < s->thread_count; ++i )
  {
    if ( pthread_create( &t->threads[ i ], &attr, thread_func, s ) )
      state_error( s, "Cannot create thread #%d", i );
  }

  pthread_attr_destroy( &attr );
}
Пример #2
0
/**
 * Battery charging task
 */
void charger_task(void)
{
	struct charge_state_context *ctx = &task_ctx;
	timestamp_t ts;
	int sleep_usec = CHARGE_POLL_PERIOD_SHORT, diff_usec, sleep_next;
	enum charge_state new_state;
	uint8_t batt_flags;

	while (1) {
#ifdef CONFIG_SB_FIRMWARE_UPDATE
		if (sb_fw_update_in_progress()) {
			task_wait_event(CHARGE_MAX_SLEEP_USEC);
			continue;
		}
#endif
		state_common(ctx);

#ifdef CONFIG_CHARGER_TIMEOUT_HOURS
		if (ctx->curr.state == PWR_STATE_CHARGE &&
		    ctx->charge_state_updated_time.val +
		    CONFIG_CHARGER_TIMEOUT_HOURS * HOUR < ctx->curr.ts.val) {
			CPRINTS("Charge timed out after %d hours",
				CONFIG_CHARGER_TIMEOUT_HOURS);
			charge_force_idle(1);
		}
#endif /* CONFIG_CHARGER_TIMEOUT_HOURS */

		switch (ctx->prev.state) {
		case PWR_STATE_INIT:
		case PWR_STATE_REINIT:
			new_state = state_init(ctx);
			break;
		case PWR_STATE_IDLE0:
			new_state = state_idle(ctx);
			/* If still idling, move from IDLE0 to IDLE */
			if (new_state == PWR_STATE_UNCHANGE)
				new_state = PWR_STATE_IDLE;
			break;
		case PWR_STATE_IDLE:
			new_state = state_idle(ctx);
			break;
		case PWR_STATE_DISCHARGE:
			new_state = state_discharge(ctx);
			break;
		case PWR_STATE_CHARGE:
			new_state = state_charge(ctx);
			if (new_state == PWR_STATE_UNCHANGE &&
			    (ctx->curr.batt.state_of_charge >=
			     BATTERY_LEVEL_NEAR_FULL)) {
				/* Almost done charging */
				new_state = PWR_STATE_CHARGE_NEAR_FULL;
			}
			break;

		case PWR_STATE_CHARGE_NEAR_FULL:
			new_state = state_charge(ctx);
			if (new_state == PWR_STATE_UNCHANGE &&
			    (ctx->curr.batt.state_of_charge <
			     BATTERY_LEVEL_NEAR_FULL)) {
				/* Battery below almost-full threshold. */
				new_state = PWR_STATE_CHARGE;
			}
			break;
		case PWR_STATE_ERROR:
			new_state = state_error(ctx);
			break;
		default:
			CPRINTS("Charge state %d undefined",
				ctx->curr.state);
			ctx->curr.state = PWR_STATE_ERROR;
			new_state = PWR_STATE_ERROR;
		}

		if (state_machine_force_idle &&
		    ctx->prev.state != PWR_STATE_IDLE0 &&
		    ctx->prev.state != PWR_STATE_IDLE &&
		    ctx->prev.state != PWR_STATE_INIT &&
		    ctx->prev.state != PWR_STATE_REINIT)
			new_state = PWR_STATE_REINIT;

		if (new_state) {
			ctx->curr.state = new_state;
			CPRINTS("Charge state %s -> %s after %.6ld sec",
				state_name[ctx->prev.state],
				state_name[new_state],
				ctx->curr.ts.val -
				ctx->charge_state_updated_time.val);
			ctx->charge_state_updated_time = ctx->curr.ts;
			hook_notify(HOOK_CHARGE_STATE_CHANGE);
		}

		switch (new_state) {
		case PWR_STATE_IDLE0:
			/*
			 * First time transitioning from init -> idle.  Don't
			 * set the flags or LED yet because we may transition
			 * to charging on the next call and we don't want to
			 * blink the LED green.
			 */
			sleep_usec = CHARGE_POLL_PERIOD_SHORT;
			break;
		case PWR_STATE_CHARGE_NEAR_FULL:
			/*
			 * Battery is almost charged.  The last few percent
			 * take a loooong time, so fall through and look like
			 * we're charged.  This mirrors similar hacks at the
			 * ACPI/kernel/UI level.
			 */
		case PWR_STATE_IDLE:
			batt_flags = *ctx->memmap_batt_flags;
			batt_flags &= ~EC_BATT_FLAG_CHARGING;
			batt_flags &= ~EC_BATT_FLAG_DISCHARGING;
			*ctx->memmap_batt_flags = batt_flags;

			/* Charge done */
			sleep_usec = (new_state == PWR_STATE_IDLE
				      ? CHARGE_POLL_PERIOD_LONG
				      : CHARGE_POLL_PERIOD_CHARGE);
			break;
		case PWR_STATE_DISCHARGE:
			batt_flags = *ctx->memmap_batt_flags;
			batt_flags &= ~EC_BATT_FLAG_CHARGING;
			batt_flags |= EC_BATT_FLAG_DISCHARGING;
			*ctx->memmap_batt_flags = batt_flags;
			sleep_usec = CHARGE_POLL_PERIOD_LONG;
			break;
		case PWR_STATE_CHARGE:
			batt_flags = *ctx->memmap_batt_flags;
			batt_flags |= EC_BATT_FLAG_CHARGING;
			batt_flags &= ~EC_BATT_FLAG_DISCHARGING;
			*ctx->memmap_batt_flags = batt_flags;

			/* Charging */
			sleep_usec = CHARGE_POLL_PERIOD_CHARGE;
			break;
		case PWR_STATE_ERROR:
			/* Error */
			sleep_usec = CHARGE_POLL_PERIOD_CHARGE;
			break;
		case PWR_STATE_UNCHANGE:
			/* Don't change sleep duration */
			break;
		default:
			/* Other state; poll quickly and hope it goes away */
			sleep_usec = CHARGE_POLL_PERIOD_SHORT;
		}

#ifdef CONFIG_EXTPOWER_FALCO
		watch_adapter_closely(ctx);
		sleep_usec = EXTPOWER_FALCO_POLL_PERIOD;
#endif

		/* Show charging progress in console */
		charging_progress(ctx);

		ts = get_time();
		diff_usec = (int)(ts.val - ctx->curr.ts.val);
		sleep_next = sleep_usec - diff_usec;

		if (ctx->curr.state == PWR_STATE_DISCHARGE &&
		    chipset_in_state(CHIPSET_STATE_ANY_OFF |
				     CHIPSET_STATE_SUSPEND)) {
			/*
			 * Discharging and system is off or suspended, so no
			 * need to poll frequently.  charge_hook() will wake us
			 * up if anything important changes.
			 */
			sleep_next = CHARGE_POLL_PERIOD_VERY_LONG - diff_usec;
		} else if (sleep_next < CHARGE_MIN_SLEEP_USEC) {
			sleep_next = CHARGE_MIN_SLEEP_USEC;
		} else if (sleep_next > CHARGE_MAX_SLEEP_USEC) {
			sleep_next = CHARGE_MAX_SLEEP_USEC;
		}

		task_wait_event(sleep_next);
	}
}