/* * 能否假设使用到交互功能的时候,实时性能已经不重要 * 2012.12.12 */ static void Tty_copy_to_cook(tty_t * tty) { byte_t c = 0; CRITICAL_DECLARE(tty->tty_lock); CRITICAL_BEGIN(); /* 输入缓冲区有数据才能对其进行加工 */ while( !TQ_IS_EMPTY(tty->tty_read_queue) ) { TQ_GET_CHAR(tty->tty_read_queue,c); switch(c) { case CHAR_BACK: if( TQ_IS_EMPTY(tty->tty_second_queue) ) continue; TQ_DEC(tty->tty_second_queue.tq_head); break; default: TQ_PUT_CHAR(tty->tty_second_queue,c); break; } } CRITICAL_END(); }
void win_unmap( segix_t segix, void **pp ) { win_t *winp; CRITICAL_BEGIN(); /* verify window mapped */ ASSERT( segix < tranp->t_segmaplen ); winp = tranp->t_segmap[segix]; ASSERT( winp ); /* validate p */ ASSERT( pp ); ASSERT( *pp ); ASSERT( *pp >= winp->w_p ); ASSERT( *pp < ( void * )( ( char * )( winp->w_p ) + tranp->t_segsz )); /* decrement the reference count. if zero, place at tail of LRU list. */ ASSERT( winp->w_refcnt > 0 ); winp->w_refcnt--; ASSERT( ! winp->w_prevp ); ASSERT( ! winp->w_nextp ); if ( winp->w_refcnt == 0 ) { if ( tranp->t_lrutailp ) { ASSERT( tranp->t_lruheadp ); winp->w_prevp = tranp->t_lrutailp; tranp->t_lrutailp->w_nextp = winp; tranp->t_lrutailp = winp; } else { ASSERT( ! tranp->t_lruheadp ); ASSERT( ! winp->w_prevp ); tranp->t_lruheadp = winp; tranp->t_lrutailp = winp; } ASSERT( ! winp->w_nextp ); } /* zero the caller's pointer */ *pp = 0; CRITICAL_END(); }
/* 2012.12.06*/ void * Tty_echo_hook_set (int ttyid,void (* echo)(byte_t)) { tty_t * tty = tty_pool + ttyid; void * handle = NULL; CRITICAL_DECLARE(tty->tty_lock); #ifdef _CFG_CHECK_PARAMETER_ if( ttyid >= TTY_MAX ) return NULL; if( NULL == echo ) return NULL; #endif /* _CFG_CHECK_PARAMETER_ */ CRITICAL_BEGIN(); handle = tty->tty_echo_hook; tty->tty_echo_hook = echo; CRITICAL_END(); return handle; }
/* ////////////////////////////////////////////////////////////////////////////////////////// // 名 称 : Tty_read // // 功 能 : // // 参 数 : // ttyid : int // 说明: tty编号 // // c : byte_t // 说明: 需要放入tty的数据 // // 返回值 : // 类型 :result_t // 说明 : // // 注 意: // // 变更记录: // 时间 | 作 者 | 说 明 //======================================================================================== // 2013-12-05 // 2011-11-11 | | ////////////////////////////////////////////////////////////////////////////////////////// */ int Tty_read(int ttyid,void * buffer,size_t size) { tty_t * tty = tty_pool + ttyid; byte_t * buf = buffer; byte_t c = 0; CRITICAL_DECLARE(tty->tty_lock); #ifdef _CFG_CHECK_PARAMETER_ if( ttyid >= TTY_MAX ) return -1; if( NULL == buffer ) return -1; #endif /* _CFG_CHECK_PARAMETER_ */ /* 终止条件是缓冲区满 */ TTY_LOCK(tty); while( size ) { CRITICAL_BEGIN(); if( TQ_IS_EMPTY(tty->tty_second_queue) ) { /* 缓冲区空需要等待数据 */ Proc_wait_on(&(tty->tty_wait)); TTY_FREE(tty); /* */ CRITICAL_END(); Proc_sched(0); TTY_LOCK(tty); } else { TQ_GET_CHAR(tty->tty_second_queue,c); CRITICAL_END(); *buf++ = c; if( CHAR_CR == c && ( tty->tty_termios.temo_type & TERMIOS_TYPE_TTY ) ) { /* 如果TTY是终端,遇到回车符需要返回。将回车符修改为0 */ *--buf = 0; break; } --size; } } TTY_FREE(tty); return buf - (byte_t *)buffer; }
void win_map( segix_t segix, void **pp ) { off64_t segoff; win_t *winp; CRITICAL_BEGIN(); #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE | MLOG_NOLOCK, "win_map(segix=%u,addr=%p)\n", segix, pp); #endif /* resize the array if necessary */ if ( segix >= tranp->t_segmaplen ) win_segmap_resize( segix ); /* see if segment already mapped. if ref cnt zero, * remove from LRU list. */ winp = tranp->t_segmap[segix]; if ( winp ) { #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE | MLOG_NOLOCK, "win_map(): requested segment already mapped\n"); #endif if ( winp->w_refcnt == 0 ) { ASSERT( tranp->t_lruheadp ); ASSERT( tranp->t_lrutailp ); if ( tranp->t_lruheadp == winp ) { if ( tranp->t_lrutailp == winp ) { tranp->t_lruheadp = 0; tranp->t_lrutailp = 0; } else { tranp->t_lruheadp = winp->w_nextp; tranp->t_lruheadp->w_prevp = 0; } } else { if ( tranp->t_lrutailp == winp ) { tranp->t_lrutailp = winp->w_prevp; tranp->t_lrutailp->w_nextp = 0; } else { winp->w_prevp->w_nextp = winp->w_nextp; winp->w_nextp->w_prevp = winp->w_prevp; } } winp->w_prevp = 0; winp->w_nextp = 0; } else { ASSERT( ! winp->w_prevp ); ASSERT( ! winp->w_nextp ); } winp->w_refcnt++; *pp = winp->w_p; CRITICAL_END(); return; } /* Allocate a new descriptor if we haven't yet hit the maximum, * otherwise reuse any descriptor on the LRU list. */ if ( tranp->t_wincnt < tranp->t_winmax ) { #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE | MLOG_NOLOCK, "win_map(): create a new window\n"); #endif winp = ( win_t * )calloc( 1, sizeof( win_t )); ASSERT( winp ); tranp->t_wincnt++; } else if ( tranp->t_lruheadp ) { /* REFERENCED */ intgen_t rval; #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE | MLOG_NOLOCK, "win_map(): get head from lru freelist & unmap\n"); #endif ASSERT( tranp->t_lrutailp ); winp = tranp->t_lruheadp; tranp->t_lruheadp = winp->w_nextp; if ( tranp->t_lruheadp ) { tranp->t_lruheadp->w_prevp = 0; } else { tranp->t_lrutailp = 0; } tranp->t_segmap[winp->w_segix] = NULL; rval = munmap( winp->w_p, tranp->t_segsz ); ASSERT( ! rval ); memset( ( void * )winp, 0, sizeof( win_t )); } else { ASSERT( tranp->t_wincnt == tranp->t_winmax ); *pp = NULL; CRITICAL_END(); mlog( MLOG_NORMAL | MLOG_WARNING, _( "all map windows in use. Check virtual memory limits\n")); return; } /* calculate offset of segment */ segoff = segix * ( off64_t )tranp->t_segsz; /* map the window */ ASSERT( tranp->t_segsz >= 1 ); ASSERT( tranp->t_firstoff <= OFF64MAX - segoff - ( off64_t )tranp->t_segsz + 1ll ); ASSERT( ! ( tranp->t_segsz % pgsz )); ASSERT( ! ( ( tranp->t_firstoff + segoff ) % ( off64_t )pgsz )); #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE | MLOG_NOLOCK, "win_map(): mmap segment at %lld, size = %llu\n", ( off64_t )( tranp->t_firstoff + segoff ), tranp->t_segsz); #endif tranp->t_winmmaps++; winp->w_p = mmap_autogrow( tranp->t_segsz, tranp->t_fd, ( off64_t )( tranp->t_firstoff + segoff )); if ( winp->w_p == (void *)-1 ) { int error = errno; mlog( MLOG_NORMAL | MLOG_ERROR, _( "win_map(): unable to map a node segment of size %d at %d: %s\n"), tranp->t_segsz, tranp->t_firstoff + segoff, strerror( error )); tranp->t_wincnt--; tranp->t_winmax--; CRITICAL_END(); free(winp); if (error == ENOMEM && tranp->t_lruheadp) { mlog( MLOG_NORMAL | MLOG_ERROR, _("win_map(): try to select a different win_t\n")); win_map(segix, pp); return; } *pp = NULL; return; } winp->w_segix = segix; ASSERT( winp->w_refcnt == 0 ); winp->w_refcnt++; tranp->t_segmap[winp->w_segix] = winp; *pp = winp->w_p; CRITICAL_END(); }
/* ////////////////////////////////////////////////////////////////////////////////////////// // 名 称 : Tty_put_char // // 功 能 : // // 参 数 : // ttyid : int // 说明: tty编号 // // c : byte_t // 说明: 需要放入tty的数据 // // 返回值 : // 类型 :result_t // 说明 : // // 注 意: 在中断内调用 // // 变更记录: // 时间 | 作 者 | 说 明 //======================================================================================== // 2013-12-05 // 2011-11-11 | | ////////////////////////////////////////////////////////////////////////////////////////// */ result_t Tty_put_char(int ttyid,byte_t c) { tty_t * tty = tty_pool + ttyid; result_t result = RESULT_SUCCEED; CRITICAL_DECLARE(tty->tty_lock ); if( ttyid >= TTY_MAX ) return result; CRITICAL_BEGIN(); /* * 1、普通tty缓冲区满则丢弃数据,因为并不一定有等待数据的进程 * 2、如果是交互终端,则需要留下回车符和退格符的空间 */ if( TQ_LEFT(tty->tty_second_queue) == 0 || ( tty->tty_termios.temo_type == TERMIOS_TYPE_TTY && !( TQ_LEFT(tty->tty_second_queue) > 4 || CHAR_BACK == c || CHAR_CR == c ) ) ) { CRITICAL_END(); return RESULT_FAILED; } TQ_PUT_CHAR( tty->tty_read_queue,c); CRITICAL_END(); /* 定义了数据加工标志,则要对数据进行加工。 */ if( tty->tty_termios.temo_iflags & TERMIOS_IFLAG_NEED_COOK ) Tty_copy_to_cook(tty); else { TQ_INC((tty->tty_read_queue).tq_tail); TQ_PUT_CHAR(tty->tty_second_queue,c); } /* 如果终端定义了回显,也就是实时输出,则需要立即输出获得的数据 */ if( tty->tty_termios.temo_oflags & TERMIOS_OFLAG_ECHO ) { /* * 如果进入密码模式,一般的字符显示改为*号 * 控制字符不改变显示 */ if( tty->tty_termios.temo_oflags & TERMIOS_OFLAG_PSW ) { switch(c) { case CHAR_CR: case CHAR_BACK: break; default: c = '*'; break; } } tty->tty_echo_hook(c); } switch(tty->tty_termios.temo_type) { case TERMIOS_TYPE_TTY: /* 交互终端对于回车符需要唤醒等待输入的进程 */ if( CHAR_CR == c ) TTY_WAKEUP(tty); break; default: /* 一般的tty在缓冲区满的时候,需要唤醒等待的进程 */ if( TQ_LEFT(tty->tty_second_queue) == 0 ) TTY_WAKEUP(tty); break; } return RESULT_SUCCEED; }