1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (c) 2002 Cray Inc.
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Lustre; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * This file provides the 'library' side for the process-based nals.
24 * it is responsible for communication with the 'api' side and
25 * providing service to the generic portals 'library'
26 * implementation. 'library' might be better termed 'communication'
35 #include <procbridge.h>
36 #include <sys/types.h>
37 #include <sys/socket.h>
41 //#include <util/pqtimer.h>
44 /* the following functions are stubs to satisfy the nal definition
45 without doing anything particularily useful*/
47 static int nal_write(nal_cb_t *nal,
53 memcpy(dst_addr, src_addr, len);
57 static int nal_read(nal_cb_t * nal,
63 memcpy(dst_addr, src_addr, len);
67 static void *nal_malloc(nal_cb_t *nal,
70 void *buf = malloc(len);
74 static void nal_free(nal_cb_t *nal,
81 static void nal_printf(nal_cb_t *nal,
93 static void nal_cli(nal_cb_t *nal,
99 static void nal_sti(nal_cb_t *nal,
100 unsigned long *flags)
105 static int nal_dist(nal_cb_t *nal,
114 /* Function: data_from_api
115 * Arguments: t: the nal state for this interface
116 * Returns: whether to continue reading from the pipe
118 * data_from_api() reads data from the api side in response
121 * We define data_failure() for syntactic convenience
122 * of unix error reporting.
125 #define data_failure(operand,fd,buffer,length)\
126 if(syscall(SYS_##operand,fd,buffer,length)!=length){\
127 lib_fini(b->nal_cb);\
130 static int data_from_api(void *arg)
133 procbridge p=(procbridge)b->local;
134 /* where are these two sizes derived from ??*/
135 char arg_block[ 256 ];
136 char ret_block[ 128 ];
137 ptl_size_t arg_len,ret_len;
141 data_failure(read,fd, &index, sizeof(index));
143 if (index==PTL_FINI) {
145 if (b->shutdown) (*b->shutdown)(b);
146 syscall(SYS_write, p->from_lib[1],&b->alive,sizeof(b->alive));
148 /* a heavy-handed but convenient way of shutting down
149 the lower side thread */
153 data_failure(read,fd, &arg_len, sizeof(arg_len));
154 data_failure(read,fd, &ret_len, sizeof(ret_len));
155 data_failure(read,fd, arg_block, arg_len);
157 lib_dispatch(b->nal_cb, NULL, index, arg_block, ret_block);
159 data_failure(write,p->from_lib[1],ret_block, ret_len);
166 static void wakeup_topside(void *z)
169 procbridge p=b->local;
171 pthread_mutex_lock(&p->mutex);
172 pthread_cond_broadcast(&p->cond);
173 pthread_mutex_unlock(&p->mutex);
177 /* Function: nal_thread
178 * Arguments: z: an opaque reference to a nal control structure
179 * allocated and partially populated by the api level code
180 * Returns: nothing, and only on error or explicit shutdown
182 * This function is the entry point of the pthread initiated on
183 * the api side of the interface. This thread is used to handle
184 * asynchronous delivery to the application.
186 * We define a limit macro to place a ceiling on limits
187 * for syntactic convenience
189 #define LIMIT(x,y,max)\
190 if ((unsigned int)x > max) y = max;
192 extern int tcpnal_init(bridge);
194 nal_initialize nal_table[PTL_IFACE_MAX]={0,tcpnal_init,0};
196 void *nal_thread(void *z)
199 procbridge p=b->local;
201 ptl_pid_t pid_request;
203 ptl_ni_limits_t desired;
204 ptl_ni_limits_t actual;
206 b->nal_cb=(nal_cb_t *)malloc(sizeof(nal_cb_t));
207 b->nal_cb->nal_data=b;
208 b->nal_cb->cb_read=nal_read;
209 b->nal_cb->cb_write=nal_write;
210 b->nal_cb->cb_malloc=nal_malloc;
211 b->nal_cb->cb_free=nal_free;
212 b->nal_cb->cb_map=NULL;
213 b->nal_cb->cb_unmap=NULL;
214 b->nal_cb->cb_printf=nal_printf;
215 b->nal_cb->cb_cli=nal_cli;
216 b->nal_cb->cb_sti=nal_sti;
217 b->nal_cb->cb_dist=nal_dist;
220 register_io_handler(p->to_lib[0],READ_HANDLER,data_from_api,(void *)b);
222 if(!(rc = syscall(SYS_read, p->to_lib[0], &pid_request, sizeof(pid_request))))
223 perror("procbridge read from api");
224 if(!(rc = syscall(SYS_read, p->to_lib[0], &desired, sizeof(ptl_ni_limits_t))))
225 perror("procbridge read from api");
226 if(!(rc = syscall(SYS_read, p->to_lib[0], &nal_type, sizeof(nal_type))))
227 perror("procbridge read from api");
230 LIMIT(desired.max_match_entries,actual.max_match_entries,MAX_MES);
231 LIMIT(desired.max_mem_descriptors,actual.max_mem_descriptors,MAX_MDS);
232 LIMIT(desired.max_event_queues,actual.max_event_queues,MAX_EQS);
233 LIMIT(desired.max_atable_index,actual.max_atable_index,MAX_ACLS);
234 LIMIT(desired.max_ptable_index,actual.max_ptable_index,MAX_PTLS);
236 set_address(b,pid_request);
238 if (nal_table[nal_type]) rc=(*nal_table[nal_type])(b);
239 /* initialize the generic 'library' level code */
241 rc = lib_init(b->nal_cb,
245 actual.max_ptable_index,
246 actual.max_atable_index);
249 * Whatever the initialization returned is passed back to the
250 * user level code for further interpretation. We just exit if
251 * it is non-zero since something went wrong.
253 /* this should perform error checking */
255 write(p->from_lib[1], &actual, sizeof(ptl_ni_limits_t));
257 syscall(SYS_write, p->from_lib[1], &rc, sizeof(rc));
260 /* the thunk function is called each time the timer loop
261 performs an operation and returns to blocking mode. we
262 overload this function to inform the api side that
263 it may be interested in looking at the event queue */
264 register_thunk(wakeup_topside,b);