⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 io.c

📁 嵌入式下基于MiniGUI的Web Browser
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * File: IO.c * * Copyright (C) 2000, 2001, 2002 Jorge Arellano Cid <jcid@dillo.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *//* * Dillo's signal driven IO engine */#include <pthread.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <sys/stat.h>#include <sys/uio.h>#include <sys/socket.h>#include "../msg.h"#include "../chain.h"#include "../list.h"#include "../klist.h"#include "io.h"#define DEBUG_LEVEL 5#include "../debug.h"/* * Symbolic defines for shutdown() function * (Not defined in the same header file, for all distros --Jcid) */#define IO_StopRd   0#define IO_StopWr   1#define IO_StopRdWr 2/* * Local data */static Klist_t *ValidIOs = NULL; /* Active IOs list. It holds pointers to                                  * IOData_t structures. *//* *  Forward declarations */void a_IO_ccc(int Op, int Branch, int Dir, ChainLink *Info,              void *Data1, void *Data2);/* * Debug procedure...static void IO_print_cond_status(gchar  *str,  GIOCondition  cond,                                 GIOChannel *gio, gint key){   MSG("%s FD=%d key=%d [", str, g_io_channel_unix_get_fd(gio), key);   MSG(cond & G_IO_IN ? "G_IO_IN " : "");   MSG(cond & G_IO_OUT ? "G_IO_OUT " : "");   MSG(cond & G_IO_PRI ? "G_IO_PRI " : "");   MSG(cond & G_IO_ERR ? "G_IO_ERR " : "");   MSG(cond & G_IO_HUP ? "G_IO_HUP " : "");   MSG(cond & G_IO_NVAL ? "G_IO_NVAL " : "");   MSG("]\n");} *//* IO API  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *//* * Return a newly created, and initialized, 'io' struct */IOData_t *a_IO_new(gint op, gint fd){   IOData_t *io = g_new0(IOData_t, 1);   io->Op = op;   io->FD = fd;   io->GioCh = g_io_channel_unix_new(fd);   io->Flags = 0;   io->Key = 0;#ifdef ENABLE_SSL   io->bio = NULL;#endif   return io;}/* * Set the transfer buffer. * (if we allocate it, we free it) */void a_IO_set_buf(IOData_t *io, void *Buf, size_t BufSize){   if (io->Flags & IOFlag_FreeIOBuf) {      g_free(io->BufStart);      io->Flags &= ~IOFlag_FreeIOBuf;   }   if (!Buf && BufSize) {      io->BufStart = io->Buf = g_malloc(BufSize);      io->BufSize = BufSize;      io->Flags |= IOFlag_FreeIOBuf;   } else {      io->BufStart = io->Buf = Buf;      io->BufSize = BufSize;   }}/* * Add a new chunk to the transfer buffer. * (we allocate it, so we free it) */void a_IO_add_buf(IOData_t *io, void *Buf, size_t BufSize){   size_t offset;   if (BufSize == 0) {      /* This is the last chunk */      io->Flags |= IOFlag_ForceClose;      return;   }   offset = (io->Buf) ? (gchar*)io->Buf - (gchar*)io->BufStart : 0;   io->BufStart = g_realloc(io->BufStart, offset + io->BufSize + BufSize);   memcpy((gchar*)io->BufStart + offset + io->BufSize, Buf, BufSize);   io->Buf = (gchar*)io->BufStart + offset;   io->BufSize += BufSize;   io->Flags |= IOFlag_FreeIOBuf;}/* * Return transfer buffer. *void a_IO_get_buf(IOData_t *io, void **Buf, size_t *BufSize){   *Buf = io->Buf;   *BufSize = io->BufSize;} */typedef struct {   pthread_t thrID;        /* Thread id */   pthread_mutex_t mut;   pthread_cond_t cond;   gint FD;   void *Key;   void *Buf1Start;   void *Buf1;   size_t Buf1Size;   void *Buf2;   size_t Buf2Size;   gint LastChunk;   gint CloseFD;   gint Done;} thr_data_t;/* Active data for threaded chunk transfers */static thr_data_t **ThrData = NULL;static gint ThrDataSize = 0;static gint ThrDataMax = 8;/* * Create a new ThrData node */static thr_data_t *IO_thrdata_new(gint FD, void *Key){   thr_data_t *data;   data = g_new(thr_data_t, 1);   pthread_mutex_init(&data->mut, NULL);   pthread_cond_init(&data->cond, NULL);   data->FD = FD;   data->Key = Key;   data->Buf1Start = data->Buf1 = data->Buf2 = NULL;   data->Buf1Size = data->Buf2Size = 0;   data->LastChunk = 0;   data->CloseFD = 0;   data->Done = 0;   return data;}/* * Free a ThrData node */static void IO_thrdata_free(thr_data_t *td){   /* EBUSY should not happen: IO_thrdata_free is called after the    * thread is done */   while (pthread_cond_destroy(&td->cond) == EBUSY) {      g_warning("IO_thrdata_free: EBUSY\n");      if (pthread_cancel(td->thrID) == ESRCH)         break;   }   pthread_mutex_destroy(&td->mut);   g_free(td);}/* * Search data node for a FD *  - The FD is searched using a Key because using the FD itself may fail *  due to a race condition between the FD close and its reuse. *  - This function also frees already closed data. */static thr_data_t *IO_thrdata_find(void *Key){   gint i, idx = -1;   _MSG("TL(%p): [", Key);   for (i = 0; i < ThrDataSize; ++i) {      _MSG(" %d%s", ThrData[i]->FD, ThrData[i]->Done ? "D" : "");      if (ThrData[i]->Done) {         IO_thrdata_free(ThrData[i]);         a_List_remove(ThrData, i, ThrDataSize);         --i;      } else if (ThrData[i]->Key == Key) {         idx = i;         _MSG("*");      }   }   _MSG("]\n");   if (idx != -1)      return ThrData[idx];   return NULL;}/* * Write the data buffer through a FD. * [This function runs on its own thread] */static void *IO_write_chunk(void *ptr){   gint lock = 0;   thr_data_t *data = ptr;   ssize_t St;   gint st, done;   _MSG("thr::\n");   _MSG("      [thrID:%lu]\n", (gulong)data->thrID);   while (1) {      _MSG("thr:: trying to lock mutex\n");      if (!lock) {         pthread_mutex_lock(&data->mut);         lock = 1;      }      _MSG("thr:: mutex locked!\n");      _MSG("thr:: Buf1:%p Buf2:%p LastChunk:%d Done:%d\n",           data->Buf1, data->Buf2, data->LastChunk, data->Done);      if (data->Buf2) {         /* Buf1 := Buf2;  Buf2 := NULL */         g_free(data->Buf1Start);         data->Buf1Start = data->Buf1 = data->Buf2;         data->Buf1Size = data->Buf2Size;         data->Buf2 = NULL;         data->Buf2Size = 0;         _MSG("thr:: Buf1:%p Buf2:%p LastChunk:%d Done:%d\n",              data->Buf1, data->Buf2, data->LastChunk, data->Done);         pthread_mutex_unlock(&data->mut);         lock = 0;         _MSG("thr:: mutex unlocked!\n");         /*** write all ***/         done = 0;         while (!done) {            St = write(data->FD, data->Buf1, data->Buf1Size);            _MSG("thr:: St=%d\n", St);            if (St < 0) {               if (errno == EINTR) {                  continue;               } else {                  perror("IO_write_chunk");                  return NULL;               }            } else if ((size_t)St < data->Buf1Size) {               /* Not all data written */               data->Buf1 = (gchar *)data->Buf1 + St;               data->Buf1Size -= St;            } else {               /* All data in buffer written */               //sleep(1);               done = 1;            }         }      }      /* Buf1 was written, prepare the next step... */      if (!lock) {         pthread_mutex_lock(&data->mut);         lock = 1;      }      if (data->Buf2)         continue;      else if (data->LastChunk) {         /* Only pipes are closed, sockets are left for the server to close */         if (data->CloseFD) {            do               st = close(data->FD);            while (st < 0 && errno == EINTR);         }         g_free(data->Buf1Start);         data->Done = 1;         pthread_mutex_unlock(&data->mut);         _MSG("thr:: LastChunk:%d Done:%d  --Bailing out!\n",              data->LastChunk, data->Done);         return NULL;      } else {         _MSG("thr:: going to cond_wait...\n");         pthread_cond_wait(&data->cond, &data->mut);         lock = 1;      }   }/* while (1) */}/* * Write a data chunk from a pthread * (!Buf && !BufSize -> LastChunk -> close tansfer, don't close FD) * (!Buf && BufSize == 1 -> LastChunk -> close tansfer, close FD) */void a_IO_write_chunk(gint FD, void *Key, void *Buf, size_t BufSize){   thr_data_t *data;   gint new_thread = 0;   static pthread_attr_t thrATTR;   static gint thrATTRInitialized = 0;   /* set the thread attribute to the detached state */   if (!thrATTRInitialized) {      pthread_attr_init(&thrATTR);      pthread_attr_setdetachstate(&thrATTR, PTHREAD_CREATE_DETACHED);      thrATTRInitialized = 1;   }   /* Search data node for this FD */   data = IO_thrdata_find(Key);   _MSG(" a_IO_write_chunk: data=%p Buf=%p, BufSize=%d, FD=%d\n",        data, Buf, BufSize, FD);   if (!data && Buf) {      data = IO_thrdata_new(FD, Key);      a_List_add(ThrData, ThrDataSize, ThrDataMax);      ThrData[ThrDataSize] = data;      ThrDataSize++;      new_thread = 1;   }   pthread_mutex_lock(&data->mut);    if (Buf) {       data->Buf2 = g_realloc(data->Buf2, data->Buf2Size + BufSize);       memcpy((gchar*)data->Buf2 + data->Buf2Size, Buf, BufSize);       data->Buf2Size = data->Buf2Size + BufSize;    } else {       data->LastChunk = 1;       data->CloseFD = (BufSize == 1) ? 1 : 0;    }    pthread_cond_signal(&data->cond);   pthread_mutex_unlock(&data->mut);   if (new_thread)      pthread_create(&data->thrID, &thrATTR, IO_write_chunk, data);}/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *//* * Register an IO in ValidIOs */void IO_ins(IOData_t *io){   io->Key = a_Klist_insert(&ValidIOs, (gpointer)io);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -