1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (c) 2002 Cray Inc.
5 * Copyright (c) 2003 Cluster File Systems, Inc.
7 * This file is part of Lustre, http://www.lustre.org.
9 * Lustre is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU General Public
11 * License as published by the Free Software Foundation.
13 * Lustre is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Lustre; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * This file provides the 'library' side for the process-based nals.
25 * it is responsible for communication with the 'api' side and
26 * providing service to the generic portals 'library'
27 * implementation. 'library' might be better termed 'communication'
35 #include <procbridge.h>
36 #include <sys/types.h>
37 #include <sys/socket.h>
43 /* the following functions are stubs to satisfy the nal definition
44 without doing anything particularily useful*/
46 static ptl_err_t nal_write(nal_cb_t *nal,
52 memcpy(dst_addr, src_addr, len);
56 static ptl_err_t nal_read(nal_cb_t * nal,
62 memcpy(dst_addr, src_addr, len);
66 static void *nal_malloc(nal_cb_t *nal,
69 void *buf = malloc(len);
73 static void nal_free(nal_cb_t *nal,
80 static void nal_printf(nal_cb_t *nal,
92 static void nal_cli(nal_cb_t *nal,
95 bridge b = (bridge) nal->nal_data;
96 procbridge p = (procbridge) b->local;
98 pthread_mutex_lock(&p->mutex);
102 static void nal_sti(nal_cb_t *nal,
103 unsigned long *flags)
105 bridge b = (bridge)nal->nal_data;
106 procbridge p = (procbridge) b->local;
108 pthread_mutex_unlock(&p->mutex);
111 static void nal_callback(nal_cb_t *nal, void *private,
112 lib_eq_t *eq, ptl_event_t *ev)
114 bridge b = (bridge)nal->nal_data;
115 procbridge p = (procbridge) b->local;
117 /* holding p->mutex */
118 if (eq->event_callback != NULL)
119 eq->event_callback(ev);
121 pthread_cond_broadcast(&p->cond);
124 static int nal_dist(nal_cb_t *nal,
131 static void check_stopping(void *z)
134 procbridge p = b->local;
136 if ((p->nal_flags & NAL_FLAG_STOPPING) == 0)
139 pthread_mutex_lock(&p->mutex);
140 p->nal_flags |= NAL_FLAG_STOPPED;
141 pthread_cond_broadcast(&p->cond);
142 pthread_mutex_unlock(&p->mutex);
148 /* Function: nal_thread
149 * Arguments: z: an opaque reference to a nal control structure
150 * allocated and partially populated by the api level code
151 * Returns: nothing, and only on error or explicit shutdown
153 * This function is the entry point of the pthread initiated on
154 * the api side of the interface. This thread is used to handle
155 * asynchronous delivery to the application.
157 * We define a limit macro to place a ceiling on limits
158 * for syntactic convenience
160 #define LIMIT(x,y,max)\
161 if ((unsigned int)x > max) y = max;
163 extern int tcpnal_init(bridge);
165 nal_initialize nal_table[PTL_IFACE_MAX]={0,tcpnal_init,0};
167 void *nal_thread(void *z)
169 nal_init_args_t *args = (nal_init_args_t *) z;
170 bridge b = args->nia_bridge;
171 procbridge p=b->local;
173 ptl_pid_t pid_request;
175 ptl_ni_limits_t desired;
176 ptl_ni_limits_t actual;
178 b->nal_cb=(nal_cb_t *)malloc(sizeof(nal_cb_t));
179 b->nal_cb->nal_data=b;
180 b->nal_cb->cb_read=nal_read;
181 b->nal_cb->cb_write=nal_write;
182 b->nal_cb->cb_malloc=nal_malloc;
183 b->nal_cb->cb_free=nal_free;
184 b->nal_cb->cb_map=NULL;
185 b->nal_cb->cb_unmap=NULL;
186 b->nal_cb->cb_printf=nal_printf;
187 b->nal_cb->cb_cli=nal_cli;
188 b->nal_cb->cb_sti=nal_sti;
189 b->nal_cb->cb_callback=nal_callback;
190 b->nal_cb->cb_dist=nal_dist;
192 pid_request = args->nia_requested_pid;
193 desired = *args->nia_limits;
194 nal_type = args->nia_nal_type;
197 LIMIT(desired.max_match_entries,actual.max_match_entries,MAX_MES);
198 LIMIT(desired.max_mem_descriptors,actual.max_mem_descriptors,MAX_MDS);
199 LIMIT(desired.max_event_queues,actual.max_event_queues,MAX_EQS);
200 LIMIT(desired.max_atable_index,actual.max_atable_index,MAX_ACLS);
201 LIMIT(desired.max_ptable_index,actual.max_ptable_index,MAX_PTLS);
203 set_address(b,pid_request);
205 if (nal_table[nal_type]) rc=(*nal_table[nal_type])(b);
206 /* initialize the generic 'library' level code */
208 rc = lib_init(b->nal_cb,
212 actual.max_ptable_index,
213 actual.max_atable_index);
216 * Whatever the initialization returned is passed back to the
217 * user level code for further interpretation. We just exit if
218 * it is non-zero since something went wrong.
220 /* this should perform error checking */
221 pthread_mutex_lock(&p->mutex);
222 p->nal_flags |= rc ? NAL_FLAG_STOPPED : NAL_FLAG_RUNNING;
223 pthread_cond_broadcast(&p->cond);
224 pthread_mutex_unlock(&p->mutex);
227 /* the thunk function is called each time the timer loop
228 performs an operation and returns to blocking mode. we
229 overload this function to inform the api side that
230 it may be interested in looking at the event queue */
231 register_thunk(check_stopping,b);