Index: asp3_tinet_ecnl_rx/trunk/asp3_dcre/tinet/netapp/dhcp4_cli.c
===================================================================
--- asp3_tinet_ecnl_rx/trunk/asp3_dcre/tinet/netapp/dhcp4_cli.c	(revision 337)
+++ asp3_tinet_ecnl_rx/trunk/asp3_dcre/tinet/netapp/dhcp4_cli.c	(revision 340)
@@ -191,4 +191,20 @@
 #endif
 
+#ifdef SEM_DHCP4_CLI_TIMER
+#define DHCP4_CLI_TIMER_LOCK() do { syscall(wai_sem(SEM_DHCP4_CLI_TIMER)); } while(0)
+#define DHCP4_CLI_TIMER_UNLOCK() do { syscall(sig_sem(SEM_DHCP4_CLI_TIMER)); } while(0)
+#else
+#define DHCP4_CLI_TIMER_LOCK() do { } while(0)
+#define DHCP4_CLI_TIMER_UNLOCK() do { } while(0)
+#endif
+
+#ifdef SEM_DHCP4_CLI_READY
+#define DHCP4_CLI_READY_WAIT(ct) do { syscall(wai_sem(SEM_DHCP4_CLI_READY)); } while(0)
+#define DHCP4_CLI_READY_SIGNAL(ct) do { syscall(sig_sem(SEM_DHCP4_CLI_READY)); } while(0)
+#else
+#define DHCP4_CLI_READY_WAIT(ct) do { } while(0)
+#define DHCP4_CLI_READY_SIGNAL(ct) do { syscall(wup_tsk(ct->tskid)); } while(0)
+#endif
+
 /*
  *  dhcp4_cksum -- チェックサムの計算関数
@@ -919,8 +935,8 @@
 	int ix;
 
-	syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
+	DHCP4_CLI_TIMER_LOCK();
 	for (ix = NUM_DHCP4C_TIMERS; ix -- > 0; )
 		ct->timers[ix] = 0;
-	syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
+	DHCP4_CLI_TIMER_UNLOCK();
 	}
 
@@ -937,7 +953,7 @@
 
 	/* OFFER メッセージ受信タイムアウトを設定する。*/
-	syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
+	DHCP4_CLI_TIMER_LOCK();
 	ct->timers[DHCP4C_TIMER_RCV_OFFER] = SYSTIM2TIMER(TMO_DHCP4C_OFFER);
-	syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
+	DHCP4_CLI_TIMER_UNLOCK();
 
 	/* 送信先アドレスにローカルネットワークへのブロードキャストを設定する。*/
@@ -952,5 +968,5 @@
 	/* DISCOVER メッセージを送信する。*/
 	ct->flags |= DHCP4C_FLAG_TMOUT_SND_DISC;
-	syscall(sig_sem(SEM_DHCP4_CLI_READY));
+	DHCP4_CLI_READY_SIGNAL(ct);
 	}
 
@@ -979,9 +995,9 @@
 
 	/* EXPIRE、RENEW、REBIND タイマーを設定する。*/
-	syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
+	DHCP4_CLI_TIMER_LOCK();
 	ct->timers[DHCP4C_TIMER_EXPIRE] = SYSTIM2TIMER(ct->expire);		/* EXPIRE      までの時間 */
 	ct->timers[DHCP4C_TIMER_REBIND] = SYSTIM2TIMER(ct->rebind);		/* REBIND（T2）までの時間 */
 	ct->timers[DHCP4C_TIMER_RENEW]  = SYSTIM2TIMER(ct->renew);		/* RENEW （T1）までの時間 */
-	syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
+	DHCP4_CLI_TIMER_UNLOCK();
 
 	/* BOUND 状態に遷移する。*/
@@ -1006,7 +1022,7 @@
 	/* 遷移する状態が RENEW 以外では ACK/NAK メッセージ受信タイムアウトを設定する。*/
 	if (fsm != DHCP4_FSM_RENEW) { 
-		syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
+		DHCP4_CLI_TIMER_LOCK();
 		ct->timers[DHCP4C_TIMER_RCV_ACK] = SYSTIM2TIMER(TMO_DHCP4C_ACK);
-		syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
+		DHCP4_CLI_TIMER_UNLOCK();
 		}
 
@@ -1029,5 +1045,5 @@
 	/* REQUEST メッセージを送信する。*/
 	ct->flags |= DHCP4C_FLAG_TMOUT_SND_REQ;
-	syscall(sig_sem(SEM_DHCP4_CLI_READY));
+	DHCP4_CLI_READY_SIGNAL(ct);
 	}
 
@@ -1055,5 +1071,5 @@
 	/* RELEASE メッセージを送信する。*/
 	ct->flags |= DHCP4C_FLAG_TMOUT_SND_REL;
-	syscall(sig_sem(SEM_DHCP4_CLI_READY));
+	DHCP4_CLI_READY_SIGNAL(ct);
 	}
 
@@ -1349,7 +1365,7 @@
 
 		/* REQUEST メッセージ送信タイマーを停止する。*/
-		syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
+		DHCP4_CLI_TIMER_LOCK();
 		ct->timers[DHCP4C_TIMER_SND_REQ] = 0;
-		syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
+		DHCP4_CLI_TIMER_UNLOCK();
 
 		/*
@@ -1399,7 +1415,7 @@
 
 		/* ACK/NAK メッセージ受信タイマーを停止する。*/
-		syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
+		DHCP4_CLI_TIMER_LOCK();
 		ct->timers[DHCP4C_TIMER_RCV_ACK] = 0;
-		syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
+		DHCP4_CLI_TIMER_UNLOCK();
 
 		/*
@@ -1475,7 +1491,7 @@
 
 	/* 再送信タイムアウトを設定する。*/
-	syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
+	DHCP4_CLI_TIMER_LOCK();
 	ct->timers[DHCP4C_TIMER_SND_REQ] = SYSTIM2TIMER(ct->interval);
-	syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
+	DHCP4_CLI_TIMER_UNLOCK();
 	}
 
@@ -1511,5 +1527,5 @@
 
 	/* メッセージ送信待ちを行う。*/
-	syscall(wai_sem(SEM_DHCP4_CLI_READY));
+	DHCP4_CLI_READY_WAIT(ct);
 
 	/* SLEEP 状態に遷移する。*/
@@ -1529,7 +1545,7 @@
 
 		/* DISCOVER メッセージ送信タイマーを停止する。*/
-		syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
+		DHCP4_CLI_TIMER_LOCK();
 		ct->timers[DHCP4C_TIMER_SND_DISC] = 0;
-		syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
+		DHCP4_CLI_TIMER_UNLOCK();
 
 		/* REQUEST メッセージを送信して REQUEST 状態に遷移する。*/
@@ -1559,7 +1575,7 @@
 
 		/* OFFER メッセージ受信タイマーを停止する。*/
-		syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
+		DHCP4_CLI_TIMER_LOCK();
 		ct->timers[DHCP4C_TIMER_RCV_OFFER] = 0;
-		syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
+		DHCP4_CLI_TIMER_UNLOCK();
 
 		/* REQUEST メッセージを送信して REQUEST 状態に遷移する。*/
@@ -1614,8 +1630,10 @@
 
 	/* 再送信タイムアウトを設定する。*/
-	syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
+	DHCP4_CLI_TIMER_LOCK();
 	ct->timers[DHCP4C_TIMER_SND_DISC] = SYSTIM2TIMER(ct->interval);
-	syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
-	}
+	DHCP4_CLI_TIMER_UNLOCK();
+	}
+
+#ifdef DHCP4_CLI_TASK
 
 /*
@@ -1628,5 +1646,5 @@
 	int ix;
 
-	syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
+	DHCP4_CLI_TIMER_LOCK();
 	for (ix = NUM_DHCP4C_TIMERS; ix -- > 0; ) {
 		if (ct->timers[ix] != 0) {
@@ -1634,13 +1652,15 @@
 			if (ct->timers[ix] == 0) {
 				ct->flags = (ct->flags & ~DHCP4C_FLAG_TMOUT_MASK) | DHCP4C_FLAG_TMOUT_TIMER | ix;
-				syscall(sig_sem(SEM_DHCP4_CLI_READY));
+				DHCP4_CLI_READY_SIGNAL(ct);
 				}
 			}
 		}
-	syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
+	DHCP4_CLI_TIMER_UNLOCK();
 
 	/* 1秒毎にタイムアウトする。*/
 	timeout((callout_func)dhcpc_timer, ct, NET_TIMER_HZ);
 	}
+
+#endif
 
 /*
@@ -1748,4 +1768,6 @@
 	}
 
+#ifdef DHCP4_CLI_TASK
+
 /*
  *  dispatch_event -- イベント毎の処理
@@ -1760,5 +1782,5 @@
 
 		/* メッセージの受信とタイムアウトを待つ。*/
-		syscall(wai_sem(SEM_DHCP4_CLI_READY));
+		DHCP4_CLI_READY_WAIT(ct);
 
 		if (ct->flags & DHCP4C_FLAG_RCV_MSG) {
@@ -1778,4 +1800,6 @@
 	}
 
+#endif
+
 /*
  *  init_context -- DHCP クライアントコンテキスト構造体を初期化する。
@@ -1783,7 +1807,8 @@
 
 static void
-init_context (T_DHCP4_CLI_CONTEXT *ct, ID cepid)
+init_context (T_DHCP4_CLI_CONTEXT *ct, ID tskid, ID cepid)
 {
   	memset(ct, 0, sizeof(*ct));
+	ct->tskid	= tskid;
 	ct->cepid	= cepid;
 	ct->sc		= IF_ETHER_NIC_GET_SOFTC();
@@ -1880,5 +1905,7 @@
 
 		/* SLEEP を解除する。*/
-		wup_tsk(DHCP4_CLI_TASK);
+		context.fsm = DHCP4_FSM_WAKE;
+		context.timer = 0;
+		wup_tsk(context.tskid);
 		return E_OK;
 		}
@@ -1970,8 +1997,10 @@
 				}
 			}
-		syscall(sig_sem(SEM_DHCP4_CLI_READY));
+		DHCP4_CLI_READY_SIGNAL((&context));
 		}
 	return E_OK;
 	}
+
+#ifdef DHCP4_CLI_TASK
 
 /*
@@ -1993,5 +2022,5 @@
 
 	/* DHCP クライアントコンテキスト構造体を初期化する。*/
-	init_context(ct, (ID)exinf);
+	init_context(ct, tskid, (ID)exinf);
 	ct->fsm = DHCP4_FSM_SLEEP;
 
@@ -2037,3 +2066,107 @@
 	}
 
+#else
+
+T_DHCP4_CLI_CONTEXT *
+dhcp4_cli_initialize(ID tskid, ID cepid)
+{
+	T_DHCP4_CLI_CONTEXT *ct = &context;
+	/* DHCP クライアントコンテキスト構造体を初期化する。*/
+	init_context(ct, tskid, cepid);
+	ct->fsm = DHCP4_FSM_SLEEP;
+	ct->timer = TMO_FEVR;
+	return ct;
+	}
+
+int
+dhcp4_cli_get_timer(T_DHCP4_CLI_CONTEXT *ct)
+{
+	if (ct->fsm == DHCP4_FSM_SLEEP)
+		return TMO_FEVR;
+
+	return ct->timer;
+	}
+
+void
+dhcp4_cli_progress(T_DHCP4_CLI_CONTEXT *ct, int elapse)
+{
+	int ix;
+
+	if ((ct->fsm == DHCP4_FSM_SLEEP) || (ct->timer == TMO_FEVR))
+		return;
+
+	ct->timer -= elapse;
+	if (ct->timer > 0)
+		return;
+
+	/* 1秒毎にタイムアウトするようにタイマーを設定する。*/
+	ct->timer = 1000 * 1000;
+
+	for (ix = NUM_DHCP4C_TIMERS; ix-- > 0; ) {
+		if (ct->timers[ix] != 0) {
+			ct->timers[ix] --;
+			if (ct->timers[ix] <= 0) {
+				ct->timers[ix] = 0;
+				ct->flags = (ct->flags & ~DHCP4C_FLAG_TMOUT_MASK) | DHCP4C_FLAG_TMOUT_TIMER | ix;
+				DHCP4_CLI_READY_SIGNAL(ct);
+				}
+			}
+		}
+	}
+
+void
+dhcp4_cli_wakeup(T_DHCP4_CLI_CONTEXT *ct)
+{
+	if (ct->fsm == DHCP4_FSM_WAKE) {
+		ct->flags = 0;
+		ct->error = E_OK;
+
+		/* メッセージ構造体を初期化する。*/
+		if ((ct->error = init_cli_msg(ct)) != E_OK)
+			return;
+
+		ct->timer = 1000 * 1000;
+
+		/* SELECT 状態に遷移する。*/
+		start_select(ct);
+		}
+
+	if (ct->flags & DHCP4C_FLAG_RCV_MSG) {
+		while (ct->val_lst != NULL) {
+			ct->error = eval_rcv_msg(ct);
+			}
+		ct->flags &= ~DHCP4C_FLAG_RCV_MSG;
+		}
+	}
+
+void
+dhcp4_cli_timeout(T_DHCP4_CLI_CONTEXT *ct)
+{
+	if (ct->flags & DHCP4C_FLAG_TMOUT_MASK)
+		ct->error = dispatch_timeout(ct);
+
+	if (ct->error != E_OK || ct->fsm == DHCP4_FSM_SLEEP) {
+		/* 全ての TIMER をキャンセルする。*/
+		cancel_all_timers(ct);
+		ct->timer = TMO_FEVR;
+
+		/* メッセージ構造体を解放する。*/
+		rel_cli_msg(ct);
+
+		/* リースを解放後、再取得が指定されていなければ休止する。*/
+		if (!(ct->flags & DHCP4C_FLAG_RENEW)) {
+
+			/* 休止する。*/
+			if (ct->error == E_OK)
+				syslog(LOG_NOTICE, "[DHCP4C] lease released, go to sleep.");
+			else {
+				syslog(LOG_NOTICE, "[DHCP4C] server not available, go to sleep, error: %s.", itron_strerror(ct->error));
+				ct->error = E_OK;
+				ct->fsm = DHCP4_FSM_SLEEP;
+				}
+			}
+		}
+	}
+
+#endif /* DHCP4_CLI_TASK */
 #endif	/* of #ifdef DHCP4_CLI_CFG */
