1a9643ea8Slogwang 2a9643ea8Slogwang /** 3a9643ea8Slogwang * Tencent is pleased to support the open source community by making MSEC available. 4a9643ea8Slogwang * 5a9643ea8Slogwang * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. 6a9643ea8Slogwang * 7a9643ea8Slogwang * Licensed under the GNU General Public License, Version 2.0 (the "License"); 8a9643ea8Slogwang * you may not use this file except in compliance with the License. You may 9a9643ea8Slogwang * obtain a copy of the License at 10a9643ea8Slogwang * 11a9643ea8Slogwang * https://opensource.org/licenses/GPL-2.0 12a9643ea8Slogwang * 13a9643ea8Slogwang * Unless required by applicable law or agreed to in writing, software distributed under the 14a9643ea8Slogwang * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 15a9643ea8Slogwang * either express or implied. See the License for the specific language governing permissions 16a9643ea8Slogwang * and limitations under the License. 17a9643ea8Slogwang */ 18a9643ea8Slogwang 19a9643ea8Slogwang 20a9643ea8Slogwang /** 21a9643ea8Slogwang * @filename kqueue.h 22a9643ea8Slogwang * @info kqueue for micro thread manage 23a9643ea8Slogwang */ 24a9643ea8Slogwang 25a9643ea8Slogwang #ifndef _KQUEUE_PROXY___ 26a9643ea8Slogwang #define _KQUEUE_PROXY___ 27a9643ea8Slogwang 28a9643ea8Slogwang #include <stdlib.h> 29a9643ea8Slogwang #include <unistd.h> 30a9643ea8Slogwang #include <sys/queue.h> 31a9643ea8Slogwang 32a9643ea8Slogwang #include "ff_api.h" 33a9643ea8Slogwang 34a9643ea8Slogwang #include <set> 35a9643ea8Slogwang #include <vector> 36a9643ea8Slogwang using std::set; 37a9643ea8Slogwang using std::vector; 38a9643ea8Slogwang 39a9643ea8Slogwang #define kqueue_assert(statement) 40a9643ea8Slogwang //#define kqueue_assert(statement) assert(statement) 41a9643ea8Slogwang 42a9643ea8Slogwang namespace NS_MICRO_THREAD { 43a9643ea8Slogwang 44a9643ea8Slogwang #define KQ_EVENT_NONE 0 45a9643ea8Slogwang #define KQ_EVENT_READ 1 46a9643ea8Slogwang #define KQ_EVENT_WRITE 2 47a9643ea8Slogwang 48a9643ea8Slogwang /** 49a9643ea8Slogwang * @brief add more detail for linux <sys/queue.h>, freebsd and University of California 50a9643ea8Slogwang * @info queue.h version 8.3 (suse) diff version 8.5 (tlinux) 51a9643ea8Slogwang */ 52a9643ea8Slogwang #ifndef TAILQ_CONCAT 53a9643ea8Slogwang 54a9643ea8Slogwang #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) 55a9643ea8Slogwang #define TAILQ_FIRST(head) ((head)->tqh_first) 56a9643ea8Slogwang #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) 57a9643ea8Slogwang 58a9643ea8Slogwang #define TAILQ_LAST(head, headname) \ 59a9643ea8Slogwang (*(((struct headname *)((head)->tqh_last))->tqh_last)) 60a9643ea8Slogwang 61a9643ea8Slogwang #define TAILQ_FOREACH(var, head, field) \ 62a9643ea8Slogwang for ((var) = TAILQ_FIRST((head)); \ 63a9643ea8Slogwang (var); \ 64a9643ea8Slogwang (var) = TAILQ_NEXT((var), field)) 65a9643ea8Slogwang 66a9643ea8Slogwang #define TAILQ_CONCAT(head1, head2, field) \ 67a9643ea8Slogwang do { \ 68a9643ea8Slogwang if (!TAILQ_EMPTY(head2)) { \ 69a9643ea8Slogwang *(head1)->tqh_last = (head2)->tqh_first; \ 70a9643ea8Slogwang (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ 71a9643ea8Slogwang (head1)->tqh_last = (head2)->tqh_last; \ 72a9643ea8Slogwang TAILQ_INIT((head2)); \ 73a9643ea8Slogwang } \ 74a9643ea8Slogwang } while (0) 75a9643ea8Slogwang 76a9643ea8Slogwang #endif 77a9643ea8Slogwang 78a9643ea8Slogwang #ifndef TAILQ_FOREACH_SAFE // tlinux no this define 79a9643ea8Slogwang #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ 80a9643ea8Slogwang for ((var) = TAILQ_FIRST((head)); \ 81a9643ea8Slogwang (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ 82a9643ea8Slogwang (var) = (tvar)) 83a9643ea8Slogwang #endif 84a9643ea8Slogwang 85a9643ea8Slogwang 86a9643ea8Slogwang 87a9643ea8Slogwang 88a9643ea8Slogwang /******************************************************************************/ 89*35a81399Slogwang /* Kqueue proxy definition and implementation */ 90a9643ea8Slogwang /******************************************************************************/ 91a9643ea8Slogwang 92a9643ea8Slogwang class KqueueProxy; 93a9643ea8Slogwang class MicroThread; 94a9643ea8Slogwang 95a9643ea8Slogwang class KqueuerObj 96a9643ea8Slogwang { 97a9643ea8Slogwang protected: 98a9643ea8Slogwang int _fd; 99a9643ea8Slogwang int _events; 100a9643ea8Slogwang int _revents; 101a9643ea8Slogwang int _type; 102a9643ea8Slogwang MicroThread* _thread; 103a9643ea8Slogwang 104a9643ea8Slogwang public: 105a9643ea8Slogwang 106a9643ea8Slogwang TAILQ_ENTRY(KqueuerObj) _entry; 107a9643ea8Slogwang 108a9643ea8Slogwang explicit KqueuerObj(int fd = -1) { 109a9643ea8Slogwang _fd = fd; 110a9643ea8Slogwang _events = 0; 111a9643ea8Slogwang _revents = 0; 112a9643ea8Slogwang _type = 0; 113a9643ea8Slogwang _thread = NULL; 114a9643ea8Slogwang }; ~KqueuerObj()115a9643ea8Slogwang virtual ~KqueuerObj(){}; 116a9643ea8Slogwang 117a9643ea8Slogwang virtual int InputNotify(); 118a9643ea8Slogwang virtual int OutputNotify(); 119a9643ea8Slogwang virtual int HangupNotify(); 120a9643ea8Slogwang virtual int KqueueCtlAdd(void* args); 121a9643ea8Slogwang virtual int KqueueCtlDel(void* args); 122a9643ea8Slogwang EnableInput()123a9643ea8Slogwang void EnableInput() { _events |= KQ_EVENT_READ; }; 124a9643ea8Slogwang EnableOutput()125a9643ea8Slogwang void EnableOutput() { _events |= KQ_EVENT_WRITE; }; 126a9643ea8Slogwang DisableInput()127a9643ea8Slogwang void DisableInput() { _events &= ~KQ_EVENT_READ; }; 128a9643ea8Slogwang DisableOutput()129a9643ea8Slogwang void DisableOutput() { _events &= ~KQ_EVENT_WRITE; }; 130a9643ea8Slogwang GetOsfd()131a9643ea8Slogwang int GetOsfd() { return _fd; }; SetOsfd(int fd)132a9643ea8Slogwang void SetOsfd(int fd) { _fd = fd; }; 133a9643ea8Slogwang GetEvents()134a9643ea8Slogwang int GetEvents() { return _events; }; SetRcvEvents(int revents)135a9643ea8Slogwang void SetRcvEvents(int revents) { _revents = revents; }; GetRcvEvents()136a9643ea8Slogwang int GetRcvEvents() { return _revents; }; 137a9643ea8Slogwang GetNtfyType()138a9643ea8Slogwang int GetNtfyType() { return _type; }; Reset()139a9643ea8Slogwang virtual void Reset() { 140a9643ea8Slogwang _fd = -1; 141a9643ea8Slogwang _events = 0; 142a9643ea8Slogwang _revents = 0; 143a9643ea8Slogwang _type = 0; 144a9643ea8Slogwang _thread = NULL; 145a9643ea8Slogwang }; 146a9643ea8Slogwang SetOwnerThread(MicroThread * thread)147a9643ea8Slogwang void SetOwnerThread(MicroThread* thread) { _thread = thread; }; GetOwnerThread()148a9643ea8Slogwang MicroThread* GetOwnerThread() { return _thread; }; 149a9643ea8Slogwang 150a9643ea8Slogwang }; 151a9643ea8Slogwang 152*35a81399Slogwang typedef TAILQ_HEAD(__KqFdList, KqueuerObj) KqObjList; 153*35a81399Slogwang typedef struct kevent KqEvent; 154a9643ea8Slogwang 155a9643ea8Slogwang 156a9643ea8Slogwang class KqFdRef 157a9643ea8Slogwang { 158a9643ea8Slogwang private: 159*35a81399Slogwang int _wr_ref; 160*35a81399Slogwang int _rd_ref; 161*35a81399Slogwang int _events; 162*35a81399Slogwang int _revents; 163*35a81399Slogwang KqueuerObj* _kqobj; 164a9643ea8Slogwang 165a9643ea8Slogwang public: 166a9643ea8Slogwang KqFdRef()167a9643ea8Slogwang KqFdRef() { 168a9643ea8Slogwang _wr_ref = 0; 169a9643ea8Slogwang _rd_ref = 0; 170a9643ea8Slogwang _events = 0; 171a9643ea8Slogwang _revents = 0; 172a9643ea8Slogwang _kqobj = NULL; 173a9643ea8Slogwang }; ~KqFdRef()174a9643ea8Slogwang ~KqFdRef(){}; 175a9643ea8Slogwang SetListenEvents(int events)176a9643ea8Slogwang void SetListenEvents(int events) { 177a9643ea8Slogwang _events = events; 178a9643ea8Slogwang }; GetListenEvents()179a9643ea8Slogwang int GetListenEvents() { 180a9643ea8Slogwang return _events; 181a9643ea8Slogwang }; 182a9643ea8Slogwang SetNotifyObj(KqueuerObj * ntfy)183a9643ea8Slogwang void SetNotifyObj(KqueuerObj* ntfy) { 184a9643ea8Slogwang _kqobj = ntfy; 185a9643ea8Slogwang }; GetNotifyObj()186a9643ea8Slogwang KqueuerObj* GetNotifyObj() { 187a9643ea8Slogwang return _kqobj; 188a9643ea8Slogwang }; 189a9643ea8Slogwang AttachEvents(int event)190a9643ea8Slogwang void AttachEvents(int event) { 191a9643ea8Slogwang if (event & KQ_EVENT_READ) { 192a9643ea8Slogwang _rd_ref++; 193a9643ea8Slogwang } 194a9643ea8Slogwang if (event & KQ_EVENT_WRITE){ 195a9643ea8Slogwang _wr_ref++; 196a9643ea8Slogwang } 197a9643ea8Slogwang }; DetachEvents(int event)198a9643ea8Slogwang void DetachEvents(int event) { 199a9643ea8Slogwang if (event & KQ_EVENT_READ) { 200a9643ea8Slogwang if (_rd_ref > 0) { 201a9643ea8Slogwang _rd_ref--; 202a9643ea8Slogwang } else { 203a9643ea8Slogwang _rd_ref = 0; 204a9643ea8Slogwang } 205a9643ea8Slogwang } 206a9643ea8Slogwang if (event & KQ_EVENT_WRITE){ 207a9643ea8Slogwang if (_wr_ref > 0) { 208a9643ea8Slogwang _wr_ref--; 209a9643ea8Slogwang } else { 210a9643ea8Slogwang _wr_ref = 0; 211a9643ea8Slogwang } 212a9643ea8Slogwang } 213a9643ea8Slogwang }; 214a9643ea8Slogwang 215*35a81399Slogwang ReadRefCnt()216a9643ea8Slogwang int ReadRefCnt() { return _rd_ref; }; WriteRefCnt()217a9643ea8Slogwang int WriteRefCnt() { return _wr_ref; }; 218a9643ea8Slogwang 219a9643ea8Slogwang }; 220a9643ea8Slogwang 221a9643ea8Slogwang 222a9643ea8Slogwang class KqueueProxy 223a9643ea8Slogwang { 224a9643ea8Slogwang public: 225a9643ea8Slogwang static const int DEFAULT_MAX_FD_NUM = 100000; 226a9643ea8Slogwang 227a9643ea8Slogwang private: 228a9643ea8Slogwang int _kqfd; 229a9643ea8Slogwang int _maxfd; 230a9643ea8Slogwang KqEvent* _evtlist; 231a9643ea8Slogwang KqFdRef* _kqrefs; 232a9643ea8Slogwang 233a9643ea8Slogwang public: 234a9643ea8Slogwang KqueueProxy(); ~KqueueProxy()235a9643ea8Slogwang virtual ~KqueueProxy(){}; 236a9643ea8Slogwang 237a9643ea8Slogwang int InitKqueue(int max_num); 238a9643ea8Slogwang void TermKqueue(void); 239a9643ea8Slogwang KqueueGetTimeout(void)240a9643ea8Slogwang virtual int KqueueGetTimeout(void) { return 0; }; KqueueSchedule(KqObjList * fdlist,KqueuerObj * fd,int timeout)241a9643ea8Slogwang virtual bool KqueueSchedule(KqObjList* fdlist, KqueuerObj* fd, int timeout) { return false; }; 242a9643ea8Slogwang 243a9643ea8Slogwang bool KqueueAdd(KqObjList& fdset); 244a9643ea8Slogwang bool KqueueDel(KqObjList& fdset); 245a9643ea8Slogwang void KqueueDispatch(void); 246a9643ea8Slogwang bool KqueueAddObj(KqueuerObj* obj); 247a9643ea8Slogwang bool KqueueDelObj(KqueuerObj* obj); 248a9643ea8Slogwang bool KqueueCtrlAdd(int fd, int new_events); 249a9643ea8Slogwang bool KqueueCtrlDel(int fd, int new_events); 250a9643ea8Slogwang bool KqueueCtrlDelRef(int fd, int new_events, bool use_ref); 251a9643ea8Slogwang KqFdRefGet(int fd)252a9643ea8Slogwang KqFdRef* KqFdRefGet(int fd) { 253a9643ea8Slogwang return ((fd >= _maxfd) || (fd < 0)) ? (KqFdRef*)NULL : &_kqrefs[fd]; 254a9643ea8Slogwang } 255a9643ea8Slogwang KqueueNtfyReg(int fd,KqueuerObj * obj)256a9643ea8Slogwang void KqueueNtfyReg(int fd, KqueuerObj* obj) { 257a9643ea8Slogwang KqFdRef* ref = KqFdRefGet(fd); 258a9643ea8Slogwang if (ref) { 259a9643ea8Slogwang ref->SetNotifyObj(obj); 260a9643ea8Slogwang } 261a9643ea8Slogwang }; 262a9643ea8Slogwang 263a9643ea8Slogwang protected: 264a9643ea8Slogwang void KqueueRcvEventList(int evtfdnum); 265a9643ea8Slogwang }; 266a9643ea8Slogwang 267a9643ea8Slogwang } 268a9643ea8Slogwang 269a9643ea8Slogwang 270a9643ea8Slogwang #endif 271