1 | /* Copyright (c) 2001, Stanford University
|
---|
2 | * All rights reserved
|
---|
3 | *
|
---|
4 | * See the file LICENSE.txt for information on redistributing this software.
|
---|
5 | */
|
---|
6 |
|
---|
7 | #include "cr_pack.h"
|
---|
8 | #include "cr_mem.h"
|
---|
9 | #include "cr_net.h"
|
---|
10 | #include "cr_pixeldata.h"
|
---|
11 | #include "cr_protocol.h"
|
---|
12 | #include "cr_error.h"
|
---|
13 | #include "packspu.h"
|
---|
14 | #include "packspu_proto.h"
|
---|
15 |
|
---|
16 | static void
|
---|
17 | packspuWriteback( const CRMessageWriteback *wb )
|
---|
18 | {
|
---|
19 | int *writeback;
|
---|
20 | crMemcpy( &writeback, &(wb->writeback_ptr), sizeof( writeback ) );
|
---|
21 | *writeback = 0;
|
---|
22 | }
|
---|
23 |
|
---|
24 | /**
|
---|
25 | * XXX Note that this routine is identical to crNetRecvReadback except
|
---|
26 | * we set *writeback=0 instead of decrementing it. Hmmm.
|
---|
27 | */
|
---|
28 | static void
|
---|
29 | packspuReadback( const CRMessageReadback *rb, unsigned int len )
|
---|
30 | {
|
---|
31 | /* minus the header, the destination pointer,
|
---|
32 | * *and* the implicit writeback pointer at the head. */
|
---|
33 |
|
---|
34 | int payload_len = len - sizeof( *rb );
|
---|
35 | int *writeback;
|
---|
36 | void *dest_ptr;
|
---|
37 | crMemcpy( &writeback, &(rb->writeback_ptr), sizeof( writeback ) );
|
---|
38 | crMemcpy( &dest_ptr, &(rb->readback_ptr), sizeof( dest_ptr ) );
|
---|
39 |
|
---|
40 | *writeback = 0;
|
---|
41 | crMemcpy( dest_ptr, ((char *)rb) + sizeof(*rb), payload_len );
|
---|
42 | }
|
---|
43 |
|
---|
44 | static void
|
---|
45 | packspuReadPixels( const CRMessageReadPixels *rp, unsigned int len )
|
---|
46 | {
|
---|
47 | crNetRecvReadPixels( rp, len );
|
---|
48 | --pack_spu.ReadPixels;
|
---|
49 | }
|
---|
50 |
|
---|
51 | static int
|
---|
52 | packspuReceiveData( CRConnection *conn, CRMessage *msg, unsigned int len )
|
---|
53 | {
|
---|
54 | if (msg->header.type == CR_MESSAGE_REDIR_PTR)
|
---|
55 | msg = (CRMessage*) msg->redirptr.pMessage;
|
---|
56 |
|
---|
57 | switch( msg->header.type )
|
---|
58 | {
|
---|
59 | case CR_MESSAGE_READ_PIXELS:
|
---|
60 | packspuReadPixels( &(msg->readPixels), len );
|
---|
61 | break;
|
---|
62 | case CR_MESSAGE_WRITEBACK:
|
---|
63 | packspuWriteback( &(msg->writeback) );
|
---|
64 | break;
|
---|
65 | case CR_MESSAGE_READBACK:
|
---|
66 | packspuReadback( &(msg->readback), len );
|
---|
67 | break;
|
---|
68 | default:
|
---|
69 | /*crWarning( "Why is the pack SPU getting a message of type 0x%x?", msg->type ); */
|
---|
70 | return 0; /* NOT HANDLED */
|
---|
71 | }
|
---|
72 | return 1; /* HANDLED */
|
---|
73 | }
|
---|
74 |
|
---|
75 | static CRMessageOpcodes *
|
---|
76 | __prependHeader( CRPackBuffer *buf, unsigned int *len, unsigned int senderID )
|
---|
77 | {
|
---|
78 | int num_opcodes;
|
---|
79 | CRMessageOpcodes *hdr;
|
---|
80 |
|
---|
81 | CRASSERT( buf );
|
---|
82 | CRASSERT( buf->opcode_current < buf->opcode_start );
|
---|
83 | CRASSERT( buf->opcode_current >= buf->opcode_end );
|
---|
84 | CRASSERT( buf->data_current > buf->data_start );
|
---|
85 | CRASSERT( buf->data_current <= buf->data_end );
|
---|
86 |
|
---|
87 | num_opcodes = buf->opcode_start - buf->opcode_current;
|
---|
88 | hdr = (CRMessageOpcodes *)
|
---|
89 | ( buf->data_start - ( ( num_opcodes + 3 ) & ~0x3 ) - sizeof(*hdr) );
|
---|
90 |
|
---|
91 | CRASSERT( (void *) hdr >= buf->pack );
|
---|
92 |
|
---|
93 | if (pack_spu.swap)
|
---|
94 | {
|
---|
95 | hdr->header.type = (CRMessageType) SWAP32(CR_MESSAGE_OPCODES);
|
---|
96 | hdr->numOpcodes = SWAP32(num_opcodes);
|
---|
97 | }
|
---|
98 | else
|
---|
99 | {
|
---|
100 | hdr->header.type = CR_MESSAGE_OPCODES;
|
---|
101 | hdr->numOpcodes = num_opcodes;
|
---|
102 | }
|
---|
103 |
|
---|
104 | *len = buf->data_current - (unsigned char *) hdr;
|
---|
105 |
|
---|
106 | return hdr;
|
---|
107 | }
|
---|
108 |
|
---|
109 |
|
---|
110 | /*
|
---|
111 | * This is called from either the Pack SPU and the packer library whenever
|
---|
112 | * we need to send a data buffer to the server.
|
---|
113 | */
|
---|
114 | void packspuFlush(void *arg )
|
---|
115 | {
|
---|
116 | ThreadInfo *thread = (ThreadInfo *) arg;
|
---|
117 | ContextInfo *ctx;
|
---|
118 | unsigned int len;
|
---|
119 | CRMessageOpcodes *hdr;
|
---|
120 | CRPackBuffer *buf;
|
---|
121 |
|
---|
122 | /* we should _always_ pass a valid <arg> value */
|
---|
123 | CRASSERT(thread && thread->inUse);
|
---|
124 | #ifdef CHROMIUM_THREADSAFE
|
---|
125 | CR_LOCK_PACKER_CONTEXT(thread->packer);
|
---|
126 | #endif
|
---|
127 | ctx = thread->currentContext;
|
---|
128 | buf = &(thread->buffer);
|
---|
129 | CRASSERT(buf);
|
---|
130 |
|
---|
131 | /* We're done packing into the current buffer, unbind it */
|
---|
132 | crPackReleaseBuffer( thread->packer );
|
---|
133 |
|
---|
134 | /*
|
---|
135 | printf("%s thread=%p thread->id = %d thread->pc=%p t2->id=%d t2->pc=%p packbuf=%p packbuf=%p\n",
|
---|
136 | __FUNCTION__, (void*) thread, (int) thread->id, thread->packer,
|
---|
137 | (int) t2->id, t2->packer,
|
---|
138 | buf->pack, thread->packer->buffer.pack);
|
---|
139 | */
|
---|
140 |
|
---|
141 | if ( buf->opcode_current == buf->opcode_start ) {
|
---|
142 | /*
|
---|
143 | printf("%s early return\n", __FUNCTION__);
|
---|
144 | */
|
---|
145 | /* XXX these calls seem to help, but might be appropriate */
|
---|
146 | crPackSetBuffer( thread->packer, buf );
|
---|
147 | crPackResetPointers(thread->packer);
|
---|
148 | #ifdef CHROMIUM_THREADSAFE
|
---|
149 | CR_UNLOCK_PACKER_CONTEXT(thread->packer);
|
---|
150 | #endif
|
---|
151 | return;
|
---|
152 | }
|
---|
153 |
|
---|
154 | hdr = __prependHeader( buf, &len, 0 );
|
---|
155 |
|
---|
156 | CRASSERT( thread->netServer.conn );
|
---|
157 |
|
---|
158 | if ( buf->holds_BeginEnd )
|
---|
159 | {
|
---|
160 | /*crDebug("crNetBarf %d, (%d)", len, buf->size);*/
|
---|
161 | crNetBarf( thread->netServer.conn, &(buf->pack), hdr, len );
|
---|
162 | }
|
---|
163 | else
|
---|
164 | {
|
---|
165 | /*crDebug("crNetSend %d, (%d)", len, buf->size);*/
|
---|
166 | crNetSend( thread->netServer.conn, &(buf->pack), hdr, len );
|
---|
167 | }
|
---|
168 |
|
---|
169 | buf->pack = crNetAlloc( thread->netServer.conn );
|
---|
170 |
|
---|
171 | /* The network may have found a new mtu */
|
---|
172 | buf->mtu = thread->netServer.conn->mtu;
|
---|
173 |
|
---|
174 | crPackSetBuffer( thread->packer, buf );
|
---|
175 |
|
---|
176 | crPackResetPointers(thread->packer);
|
---|
177 |
|
---|
178 | #ifdef CHROMIUM_THREADSAFE
|
---|
179 | CR_UNLOCK_PACKER_CONTEXT(thread->packer);
|
---|
180 | #endif
|
---|
181 | }
|
---|
182 |
|
---|
183 |
|
---|
184 | /**
|
---|
185 | * XXX NOTE: there's a lot of duplicate code here common to the
|
---|
186 | * pack, tilesort and replicate SPUs. Try to simplify someday!
|
---|
187 | */
|
---|
188 | void packspuHuge( CROpcode opcode, void *buf )
|
---|
189 | {
|
---|
190 | GET_THREAD(thread);
|
---|
191 | unsigned int len;
|
---|
192 | unsigned char *src;
|
---|
193 | CRMessageOpcodes *msg;
|
---|
194 |
|
---|
195 | CRASSERT(thread);
|
---|
196 |
|
---|
197 | /* packet length is indicated by the variable length field, and
|
---|
198 | includes an additional word for the opcode (with alignment) and
|
---|
199 | a header */
|
---|
200 | len = ((unsigned int *) buf)[-1];
|
---|
201 | if (pack_spu.swap)
|
---|
202 | {
|
---|
203 | /* It's already been swapped, swap it back. */
|
---|
204 | len = SWAP32(len);
|
---|
205 | }
|
---|
206 | len += 4 + sizeof(CRMessageOpcodes);
|
---|
207 |
|
---|
208 | /* write the opcode in just before the length */
|
---|
209 | ((unsigned char *) buf)[-5] = (unsigned char) opcode;
|
---|
210 |
|
---|
211 | /* fix up the pointer to the packet to include the length & opcode
|
---|
212 | & header */
|
---|
213 | src = (unsigned char *) buf - 8 - sizeof(CRMessageOpcodes);
|
---|
214 |
|
---|
215 | msg = (CRMessageOpcodes *) src;
|
---|
216 |
|
---|
217 | if (pack_spu.swap)
|
---|
218 | {
|
---|
219 | msg->header.type = (CRMessageType) SWAP32(CR_MESSAGE_OPCODES);
|
---|
220 | msg->numOpcodes = SWAP32(1);
|
---|
221 | }
|
---|
222 | else
|
---|
223 | {
|
---|
224 | msg->header.type = CR_MESSAGE_OPCODES;
|
---|
225 | msg->numOpcodes = 1;
|
---|
226 | }
|
---|
227 |
|
---|
228 | CRASSERT( thread->netServer.conn );
|
---|
229 | crNetSend( thread->netServer.conn, NULL, src, len );
|
---|
230 | }
|
---|
231 |
|
---|
232 | void packspuConnectToServer( CRNetServer *server )
|
---|
233 | {
|
---|
234 | crNetInit( packspuReceiveData, NULL );
|
---|
235 | crNetServerConnect( server );
|
---|
236 | }
|
---|