OLD | NEW |
(Empty) | |
| 1 //===-- SRPCStreamer.h - Stream bitcode over SRPC ------------------------===// |
| 2 // |
| 3 // The LLVM Compiler Infrastructure |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 #ifndef SRPCSTREAMER_H |
| 10 #define SRPCSTREAMER_H |
| 11 |
| 12 #include <pthread.h> |
| 13 #include <cassert> |
| 14 #include <cstdio> |
| 15 #include <cstring> |
| 16 #include <vector> |
| 17 #include "llvm/Support/DataStream.h" |
| 18 |
| 19 // Implements LLVM's interface for fetching data from a stream source. |
| 20 // Bitcode bytes from the RPC thread are placed here with PutBytes and buffered |
| 21 // until the bitcode reader calls GetBytes to remove them. |
| 22 // The blocking behavior of GetBytes and PutBytes means that if the |
| 23 // compilation happens faster than the bytes come in from the browser, the |
| 24 // whole pipeline can block waiting for the RPC thread to put more bytes. |
| 25 |
| 26 class QueueStreamer : public llvm::DataStreamer { |
| 27 public: |
| 28 QueueStreamer() : Done(false), Prod(0), Cons(0) { |
| 29 pthread_mutex_init(&Mutex, NULL); |
| 30 pthread_cond_init(&Cond, NULL); |
| 31 Bytes.resize(64 * 1024); |
| 32 } |
| 33 |
| 34 // Called by the compilation thread. Copy len bytes from the queue into |
| 35 // buf. If there are less than len bytes available, copy as many as |
| 36 // there are, signal the RPC thread, and block to wait for the rest. |
| 37 // If all bytes have been received from the browser and there are |
| 38 // fewer than len bytes available, copy all remaining bytes. |
| 39 // Return the number of bytes copied. |
| 40 virtual size_t GetBytes(unsigned char *buf, size_t len); |
| 41 |
| 42 // Called by the RPC thread. Copy len bytes from buf into the queue. |
| 43 // If there is not enough space in the queue, copy as many bytes as |
| 44 // will fit, signal the compilation thread, and block until there is |
| 45 // enough space for the rest. |
| 46 // Return the number of bytes copied. |
| 47 size_t PutBytes(unsigned char *buf, size_t len); |
| 48 |
| 49 // Called by the RPC thread. Signal that all bytes have been received, |
| 50 // so the last call to GetBytes will return the remaining bytes rather |
| 51 // than waiting for the entire requested amound. |
| 52 void SetDone(); |
| 53 |
| 54 private: |
| 55 bool Done; |
| 56 pthread_mutex_t Mutex; |
| 57 pthread_cond_t Cond; |
| 58 // Maximum size of the queue. The limitation on the queue size means that |
| 59 // if the compilation happens slower than bytes arrive from the network, |
| 60 // the queue will fill up, the RPC thread will be blocked most of the time, |
| 61 // the RPC thread on the browser side will be waiting for the SRPC to return, |
| 62 // and the buffer on the browser side will grow unboundedly until the |
| 63 // whole bitcode file arrives (which is better than having the queue on |
| 64 // the untrusted side consume all that memory). |
| 65 // The partial-copying behavior of GetBytes and PutBytes prevents deadlock |
| 66 // even if the requested number of bytes is greater than the size limit |
| 67 // (although it will of course be less efficient). |
| 68 // The initial size of the queue is expected to be smaller than this, but |
| 69 // if not, it will simply never be resized. |
| 70 const static size_t queuesize_limit_ = 256 * 1024; |
| 71 |
| 72 // Variables and functions to manage the circular queue |
| 73 std::vector<unsigned char> Bytes; |
| 74 size_t Prod; // Queue producer index |
| 75 size_t Cons; // Queue consumer index |
| 76 size_t queueSize() { |
| 77 return Prod >= Cons ? Prod - Cons : Bytes.size() - (Cons - Prod); |
| 78 } |
| 79 size_t capacityRemaining() { |
| 80 return (Prod >= Cons ? Bytes.size() - (Prod - Cons) : (Cons - Prod)) - 1; |
| 81 } |
| 82 void queueResize(); |
| 83 void queuePut(unsigned char *buf, size_t len); |
| 84 void queueGet(unsigned char *buf, size_t len); |
| 85 }; |
| 86 |
| 87 // Class to manage the compliation thread and serve as the interface from |
| 88 // the SRPC thread |
| 89 class SRPCStreamer { |
| 90 public: |
| 91 SRPCStreamer() : Error(false) {} |
| 92 // Initialize streamer, create a new thread running Callback, and |
| 93 // return a pointer to the DataStreamer the threads will use to |
| 94 // synchronize. On error, return NULL and fill in the ErrorMsg string |
| 95 llvm::DataStreamer *init(void *(*Callback)(void *), |
| 96 void *arg, std::string *ErrMsg); |
| 97 // Called by the RPC thread. Copy len bytes from buf. Return bytes copied. |
| 98 size_t gotChunk(unsigned char *bytes, size_t len); |
| 99 // Called by the RPC thread. Wait for the compilation thread to finish. |
| 100 int streamEnd(std::string *ErrMsg); |
| 101 // Called by the compilation thread. Set the error condition and also |
| 102 // terminate the thread. |
| 103 void setFatalError(const std::string& message); |
| 104 private: |
| 105 int Error; |
| 106 std::string ErrorMessage; |
| 107 QueueStreamer Q; |
| 108 pthread_t CompileThread; |
| 109 }; |
| 110 |
| 111 |
| 112 |
| 113 #endif // SRPCSTREAMER_H |
OLD | NEW |