亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來(lái)到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? threads.cpp

?? 多任務(wù)操作系統(tǒng)控制的DOS環(huán)境下的實(shí)現(xiàn)的C語(yǔ)言源程序。 利用時(shí)間片的方式
?? CPP
?? 第 1 頁(yè) / 共 2 頁(yè)
字號(hào):
//--------------------------------------------------------------------------
//
//      THREADS.CPP: body of DOS multithreading library.
//      Copyright (c) J.English 1993.
//      Author's address: je@unix.brighton.ac.uk
//
//      Permission is granted to use copy and distribute the
//      information contained in this file provided that this
//      copyright notice is retained intact and that any software
//      or other document incorporating this file or parts thereof
//      makes the source code for the library of which this file
//      is a part freely available.
//
//--------------------------------------------------------------------------
//
//      Note: this library is highly DOS specific and hence non-portable.
//      It also involves the use of assembly language and interrupt
//      functions, so it is also very compiler-specific and will need
//      modification for use with compilers other than Borland C++ 3.0
//      or later.
//
//      Revision history:
//      1.0     March 1993      Initial coding
//
//--------------------------------------------------------------------------

#include "threads.h"
#include <dos.h>

//--------------------------------------------------------------------------
//
//      Assembler sequences.
//
#define DISABLE     asm { pushf; cli; }     // save and disable interrupts
#define ENABLE      asm { popf; }           // restore interrupt state
#define PUSHAD      asm { db 0x66, 0x60; }  // push extended registers
#define POPAD       asm { db 0x66, 0x61; }  // pop extended registers
#define PUSH_FS     asm { db 0x0F, 0xA0; }  // push FS register
#define PUSH_GS     asm { db 0x0F, 0xA8; }  // push GS register
#define POP_FS      asm { db 0x0F, 0xA1; }  // pop FS register
#define POP_GS      asm { db 0x0F, 0xA9; }  // pop GS register


//--------------------------------------------------------------------------
//
//      Typedefs and constants.
//
typedef void interrupt (*Handler)(...);   // interrupt handler type
typedef volatile unsigned Register;       // interrupt handler parameter type

const unsigned MIN_STACK  = 512;          // minimum stack size
const long     DAY_LENGTH = 1573040L;     // length of day in timer ticks


//--------------------------------------------------------------------------
//
//      Global (static) variables.
//
static DOSThreadManager* current = 0;     // current thread
static DOSThreadManager* ready   = 0;     // queue of ready threads
static DOSThreadManager* delayed = 0;     // queue of delayed threads
static DOSThread* mainthread     = 0;     // thread for execution of "main"

static unsigned mainsetup = 0;            // flag set when constructing "main"
static unsigned slicesize = 1;            // length of timeslice in clock ticks
static unsigned i386;                     // flag set if executing on 386/486

static volatile unsigned threadcount = 0; // number of active threads
static volatile unsigned breakflag = 0;   // flag set by control-break
static volatile long     nextslice = 0;   // tick count for next timeslice

static volatile long far* currtime = (volatile long far*) MK_FP(0x40,0x6C);
static volatile char far* midnight = (volatile char far*) MK_FP(0x40,0x70);
                                          // timer values in BIOS data area

//--------------------------------------------------------------------------
//
//      Interrupt function pointers.
//
static Handler old_timer;                 // original timer interrupt handler
static Handler old_dos;                   // original DOS services handler
static Handler old_break;                 // original control-break handler
static Handler old_error;                 // original critical error handler

//--------------------------------------------------------------------------
//
//      Identify CPU.
//
//      This function is needed so that on 386/486 processors the
//      extended registers can be saved as part of a thread's context.
//      This is necessary in case the thread is interrupted during a
//      routine that relies on these registers being preserved.  On
//      the 386 and above, bits 12 - 14 of the flag register can be
//      written to; on earlier processors, they are either always 1
//      (8086) or always 0 (286).  The global variable "i386" is set
//      to 1 if we are executing on a 386 or above, and 0 otherwise.
//
void interrupt cputype ()
{
    //--- Assume a 386 or above to start with
    i386 = 1;

    //--- Test for an 8086 (bits 12 - 15 of flags register always 1)
    _FLAGS = 0;
    if ((_FLAGS & 0xF000) == 0xF000)
        i386 = 0;

    //--- Test for a 286 (bits 12 - 14 of flags register always 0)
    _FLAGS = 0x7000;
    if ((_FLAGS & 0x7000) == 0)
        i386 = 0;
}

//--------------------------------------------------------------------------
//
//      Class DOSNullThread.
//
//      A concrete derivation of DOSThread used for the null thread and
//      the main thread.  The main body just sits in an infinite loop.
//      A minimal stack is allocated for the purpose.
//
class DOSNullThread : public DOSThread
{
  public:
    DOSNullThread ()    : DOSThread (MIN_STACK)     { }
    
  protected:
    virtual void main ();
};

void DOSNullThread::main ()
{
    for (;;) ;                            // do nothing
}


//--------------------------------------------------------------------------
//
//      Class DOSCallMonitor.
//
//      This class is a monitor which protects against re-entrant DOS
//      calls.  It contains the DOS interrupt handler which uses "lock"
//      and "unlock" to prevent DOS being re-entered.  Since interrupt
//      routines must be static and thus have no "this" pointer, there
//      is a single instance of this class declared which the interrupt
//      handler can use when calling "lock" and "unlock".
//
class DOSCallMonitor : public DOSMonitor
{
  public:
    static void interrupt dos_int         // handle DOS service calls
        (Register, Register, Register, Register,
         Register, Register, Register, Register,
         Register, Register, Register, Register);
};

static DOSCallMonitor dos;                // instance used by DOS handler

//--------------------------------------------------------------------------
//
//      Class DOSThreadManager.
//
//      This is a support class used for maintaining queues of threads.
//      A queue is represented as a circular list of DOSThreadManagers.
//      Each queue is headed by a DOSThreadManager with a null "thread"
//      pointer, so that queues and threads can be treated in a unified
//      manner -- it guarantees that queues will never be empty, and
//      simplifies moving threads around.  The only exception to this
//      is the header for the ready queue, which has a pointer to the
//      null thread instead of a null pointer.  This guarantees that the
//      ready queue always contains a runnable thread and that the null
//      thread will only ever be executed when the ready queue contains
//      no other runnable threads.  The static member functions are also
//      included in this class so they can access the private parts of
//      the threads being controlled.
//
class DOSThreadManager
{
  public:
    DOSThreadManager (DOSThread* t = 0)   : thread (t), critflag (0)
                                          { next = prev = this; }
    void move (DOSThreadManager* t,
               DOSThread::State s);       // move to position before "t"

    DOSThreadManager* next;               // next entry in list
    DOSThreadManager* prev;               // previous entry in list
    DOSThread*        thread;             // thread for this entry
    unsigned far*     stkptr;             // stack pointer
    unsigned long     wakeup;             // wakeup time in clock ticks
    unsigned          critflag;           // flag set during critical errors

    static void far start (DOSThread* t)  // execute thread and then shut down
                                          { t->main(); t->terminate(); }

    static void           cleanup ();     // restore interrupt vectors at exit
    static void           create ();      // create main & null threads
    static void interrupt destroy ();     // destroy main & null threads
    static void interrupt schedule ();    // schedule next thread
    static void interrupt timer_int ();   // handle timer interrupts
    static void interrupt break_int ();   // handle control-break
    static void interrupt error_int       // handle critical errors
        (Register, Register, Register,
         Register, Register, Register,
         Register, Register, Register);
};

//--------------------------------------------------------------------------
//
//      Timer interrupt handler.
//
void interrupt DOSThreadManager::timer_int ()
{
    //--- call old timer handler
    old_timer ();

    //--- move current thread to back of ready queue at end of timeslice
    long now = *currtime;
    if (nextslice >= DAY_LENGTH && *midnight != 0)
        nextslice -= DAY_LENGTH;
    if (slicesize > 0 && now >= nextslice && current == ready->next)
        current->move (ready, DOSThread::READY);

    //--- make threads with expired delays runnable
    DOSThreadManager* t = delayed->next;
    DOSThreadManager* r = ready->next;
    while (t != delayed)
    {   if (t->wakeup >= DAY_LENGTH && *midnight != 0)
            t->wakeup -= DAY_LENGTH;
        if (now < t->wakeup)
            break;
        t = t->next;
        t->prev->move (r, DOSThread::READY);
    }

    //--- reschedule
    DOSThreadManager::schedule ();
}


//--------------------------------------------------------------------------
//
//      Control-break interrupt handler.
//
//      This routine just sets a flag for polling by individual threads.
//
void interrupt DOSThreadManager::break_int ()
{
    breakflag = 1;
}


//--------------------------------------------------------------------------
//
//      Critical error interrupt handler.
//
//      This calls the critical error handler for the current thread
//      (which will always be the current one, since only one thread
//      can be executing a DOS call at any one time).  "Critflag"
//      is set to inform the DOS interrupt handler that a critical
//      error is being handled.
//
void interrupt DOSThreadManager::error_int
                (Register, Register di, Register,
                 Register, Register,    Register,
                 Register, Register,    Register ax)
{
    current->critflag = 1;
    ax = current->thread->DOSerror ((ax & 0xFF00) | (di & 0x00FF)) & 0xFF;
    current->critflag = 0;
}

//--------------------------------------------------------------------------
//
//      DOS service interrupt handler.
//
//      Since DOS is not re-entrant, this handler is required to protect
//      against threads making DOS calls while there is already one in
//      progress.  It uses the monitor "dos" to prevent re-entrancy.
//      However, if a critical error occurs, the thread's critical error
//      handler may make a DOS call (but only functions 00 to 0C).  In
//      this case, the lock operation is bypassed (the thread must already
//      be in a DOS function) but the function code is checked.
//
void interrupt DOSCallMonitor::dos_int
                (Register,    Register di, Register si, Register,
                 Register es, Register dx, Register cx, Register bx,
                 Register ax, Register,    Register,    Register flags)
{
    if (current->critflag == 0)
        dos.lock ();          // prevent reentrance to DOS
    else if (ax > 0x0C)
        return;               // critical error, functions > 0x0C not allowed

    //--- load registers from stacked values
    _FLAGS = flags;
    _DI = di;
    _SI = si;
    _ES = es;
    _DX = dx;
    _CX = cx;
    _BX = bx;
    _AX = ax;

    //--- call old DOS handler
    old_dos ();
    
    //--- store registers in stacked copies
    ax = _AX;
    bx = _BX;
    cx = _CX;
    dx = _DX;
    es = _ES;
    si = _SI;
    di = _DI;
    flags = _FLAGS;
    
    if (current->critflag == 0)
        dos.unlock ();        //--- allow other threads in
}

//--------------------------------------------------------------------------
//
//      DOSThreadManager::cleanup.
//
//      This is called by the thread manager destructor when the last
//      thread is destroyed, or by "atexit" if a quick exit happens.  It
//      just restores the original interrupt vectors, so if it is called
//      multiple times during exit it won't matter.
//
void DOSThreadManager::cleanup ()
{   
    //--- unhook DOS vector by hand (can't use a DOS call to do it!)
    DISABLE;
    Handler far* dos = (Handler far*) MK_FP(0, 0x21*4);
    *dos = old_dos;
    ENABLE;

    //--- unhook other vectors
    setvect (0x08, old_timer);
    setvect (0x23, old_break);
    setvect (0x24, old_error);
}


//--------------------------------------------------------------------------
//
//      DOSThreadManager::move.
//
//      Move the caller's queue entry from its current position to the
//      position before entry "t".  This must NEVER be used to move an
//      entry which marks the head of a queue!  If "t" is a null pointer,
//      the entry is just unlinked from its current list and left hanging.
//      If the current thread is affected, a new thread is scheduled.
//
void DOSThreadManager::move (DOSThreadManager* t, DOSThread::State s)
{
    DISABLE;

    //--- change thread status
    thread->state = s;

    //--- detach thread from current queue
    next->prev = prev;
    prev->next = next;

    //--- attach before specified position (if any)
    if (t != 0)
    {   next = t;
        prev = t->prev;
        t->prev->next = this;
        t->prev = this;
    }

    ENABLE;
}

//--------------------------------------------------------------------------
//
//      DOSThreadManager::create.
//
//      Register the creation of a thread by incrementing the number of
//      threads, and initialise the system if it is the first thread to
//      be created.
//
void DOSThreadManager::create ()
{
    if (threadcount++ == 0)
    {   
        //--- set "i386" if the processor being used is a 386 or above
        cputype ();

        //--- create the delay queue
        delayed = new DOSThreadManager;

        //--- create the ready queue and the null thread
        ready = (new DOSNullThread)->entry;
        ready->move (ready, DOSThread::READY);

        //--- create the main thread (heavily bodged with "mainsetup")
        mainsetup = 1;
        mainthread = new DOSNullThread;
        mainsetup = 0;
        mainthread->entry->move (ready, DOSThread::READY);

        //--- save interrupt vectors
        old_timer = getvect (0x08);
        old_dos   = getvect (0x21);
        old_break = getvect (0x23);
        old_error = getvect (0x24);
        atexit (cleanup);                       // take care of sudden exits

        //--- hook interrupts (DOS interrupt last!)
        setvect (0x24, Handler (error_int));
        setvect (0x23, Handler (break_int));
        setvect (0x08, Handler (timer_int));
        setvect (0x21, Handler (DOSCallMonitor::dos_int));
                                                // DOS calls unsafe now

        //--- set the thread count and the current thread
        threadcount = 1;
        current = mainthread->entry;             // DOS calls safe again
        DOSThreadManager::schedule ();
    }
}

?? 快捷鍵說(shuō)明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號(hào) Ctrl + =
減小字號(hào) Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
国产一区二区精品在线观看| 69堂精品视频| 国产成人免费视频网站高清观看视频 | 国产精品色在线| 欧美国产一区视频在线观看| 国产三级久久久| 中文子幕无线码一区tr| 亚洲欧美一区二区视频| 中文字幕一区二区三区视频| 亚洲日本中文字幕区| 亚洲乱码国产乱码精品精小说| 亚洲免费观看高清完整版在线观看| 亚洲精品国久久99热| 亚洲国产sm捆绑调教视频| 亚洲国产一区二区三区| 男女男精品视频网| 国产精品 欧美精品| 91网站最新网址| 在线观看精品一区| 欧美精品丝袜久久久中文字幕| 欧美一二三四区在线| 欧美va在线播放| 国产精品麻豆久久久| 亚洲综合在线视频| 蜜臀久久久99精品久久久久久| 国产大片一区二区| 97久久久精品综合88久久| 欧美日韩一本到| 欧美xingq一区二区| 亚洲欧洲精品一区二区精品久久久| 一区二区日韩电影| 日本成人在线网站| 国产电影一区在线| 在线视频一区二区三| 欧美成人女星排名| 中文字幕av资源一区| 亚洲国产欧美在线人成| 麻豆国产欧美一区二区三区| 国产成人免费在线观看不卡| 91久久一区二区| 日韩精品中文字幕一区二区三区| 国产精品美女久久久久aⅴ国产馆 国产精品美女久久久久av爽李琼 国产精品美女久久久久高潮 | 五月婷婷色综合| 国产在线观看免费一区| 91国产精品成人| 精品国产青草久久久久福利| 亚洲欧美激情视频在线观看一区二区三区| 天堂成人国产精品一区| 成人国产精品免费观看视频| 在线播放中文一区| 国产精品国产三级国产专播品爱网| 午夜不卡在线视频| 92精品国产成人观看免费| 91精品国产综合久久精品app | 美国十次了思思久久精品导航| 成人在线综合网| 欧美一区二区人人喊爽| ...中文天堂在线一区| 久久99国产精品久久99果冻传媒| 99久久99久久综合| 亚洲精品一线二线三线无人区| 一区二区三区电影在线播| 国产精品影视在线| 欧美高清www午色夜在线视频| 国产精品国产三级国产普通话蜜臀 | 亚洲成va人在线观看| 成人avav影音| 久久九九影视网| 免费在线观看成人| 在线观看日韩av先锋影音电影院| 国产女同性恋一区二区| 美女尤物国产一区| 欧美日韩精品电影| 国产精品久久久久久久久免费桃花 | 91在线观看视频| 久久精品视频在线看| 日本亚洲一区二区| 91久久精品一区二区三区| 日本一区二区视频在线观看| 久久99精品久久久| 欧美精品久久天天躁| 亚洲色图都市小说| 成人小视频在线| 国产性天天综合网| 久久99热这里只有精品| 91精品国产91综合久久蜜臀| 亚洲福中文字幕伊人影院| 色综合天天综合色综合av | 国产真实乱对白精彩久久| 69精品人人人人| 亚洲福利国产精品| 欧美日韩视频一区二区| 一区二区激情小说| 色悠悠久久综合| 亚洲欧美另类久久久精品2019| va亚洲va日韩不卡在线观看| 欧美韩日一区二区三区| 成人性生交大合| 欧美韩国日本不卡| 成人视屏免费看| 综合色中文字幕| 91高清视频免费看| 一级日本不卡的影视| 欧美艳星brazzers| 五月天欧美精品| 日韩视频在线你懂得| 久久99精品久久久久久动态图| 欧美v国产在线一区二区三区| 久久精品久久99精品久久| 欧美videossexotv100| 国产专区综合网| 国产精品久久久久久福利一牛影视| 成人动漫中文字幕| 亚洲少妇30p| 欧美最猛性xxxxx直播| 天天做天天摸天天爽国产一区| 91精品国产综合久久精品图片| 久久 天天综合| 久久久99精品久久| 91小视频免费观看| 亚洲国产精品影院| 日韩一区二区在线观看| 精品夜夜嗨av一区二区三区| 国产日本一区二区| 日本高清免费不卡视频| 日韩av电影一区| 国产欧美一区二区精品忘忧草| 成人福利电影精品一区二区在线观看| 亚洲日本va午夜在线电影| 欧美视频在线观看一区二区| 久久成人精品无人区| 国产欧美日本一区视频| 在线视频国产一区| 免费成人美女在线观看.| 国产午夜亚洲精品午夜鲁丝片| 成人丝袜视频网| 午夜久久久久久久久| 久久久噜噜噜久久中文字幕色伊伊| av在线不卡电影| 日韩激情中文字幕| 国产欧美1区2区3区| 欧美午夜免费电影| 国产一区二区精品在线观看| 亚洲黄色性网站| 欧美mv日韩mv亚洲| 91网站黄www| 激情六月婷婷综合| 亚洲天堂网中文字| 日韩精品在线网站| 91视频免费播放| 久久av老司机精品网站导航| 最新中文字幕一区二区三区| 91精品国产麻豆| 99久久精品免费看| 久久国产剧场电影| 亚洲精品视频免费看| 欧美不卡视频一区| 欧美怡红院视频| zzijzzij亚洲日本少妇熟睡| 日韩国产精品久久| 亚洲欧美一区二区久久| 精品乱人伦一区二区三区| 色欧美88888久久久久久影院| 国产一区二区精品久久91| 午夜国产精品一区| 亚洲少妇最新在线视频| 久久久久国产免费免费| 欧美一区二区三区免费| 色系网站成人免费| 国产不卡免费视频| 免费成人在线播放| 亚洲国产裸拍裸体视频在线观看乱了| 国产性做久久久久久| 欧美刺激脚交jootjob| 欧美日韩午夜在线| 色88888久久久久久影院野外| 国产成人免费网站| 国产呦萝稀缺另类资源| 日日夜夜免费精品| 一区二区三区欧美久久| 中文字幕日韩一区| 中文文精品字幕一区二区| 欧美高清视频一二三区 | 成人网页在线观看| 狠狠色综合日日| 天堂成人免费av电影一区| 亚洲线精品一区二区三区| **性色生活片久久毛片| 中文一区二区在线观看| 国产欧美视频一区二区三区| 久久尤物电影视频在线观看| 91精品国产综合久久精品app | 午夜精品在线看| 一区二区三区四区视频精品免费 | 韩国精品主播一区二区在线观看 | 国产成人免费高清| 国产91在线|亚洲| 国产高清一区日本| 国产福利电影一区二区三区| 国产一本一道久久香蕉|