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 extern int tcpnal_init(bridge);
162 nal_initialize nal_table[PTL_IFACE_MAX]={0,tcpnal_init,0};
164 void *nal_thread(void *z)
166 nal_init_args_t *args = (nal_init_args_t *) z;
167 bridge b = args->nia_bridge;
168 procbridge p=b->local;
170 ptl_process_id_t process_id;
173 b->nal_cb=(nal_cb_t *)malloc(sizeof(nal_cb_t));
174 b->nal_cb->nal_data=b;
175 b->nal_cb->cb_read=nal_read;
176 b->nal_cb->cb_write=nal_write;
177 b->nal_cb->cb_malloc=nal_malloc;
178 b->nal_cb->cb_free=nal_free;
179 b->nal_cb->cb_map=NULL;
180 b->nal_cb->cb_unmap=NULL;
181 b->nal_cb->cb_printf=nal_printf;
182 b->nal_cb->cb_cli=nal_cli;
183 b->nal_cb->cb_sti=nal_sti;
184 b->nal_cb->cb_callback=nal_callback;
185 b->nal_cb->cb_dist=nal_dist;
187 nal_type = args->nia_nal_type;
189 /* Wierd, but this sets b->nal_cb->ni.{nid,pid}, which lib_init() is
190 * about to do from the process_id passed to it...*/
191 set_address(b,args->nia_requested_pid);
193 process_id.pid = b->nal_cb->ni.pid;
194 process_id.nid = b->nal_cb->ni.nid;
196 if (nal_table[nal_type]) rc=(*nal_table[nal_type])(b);
197 /* initialize the generic 'library' level code */
199 rc = lib_init(b->nal_cb, process_id,
200 args->nia_requested_limits,
201 args->nia_actual_limits);
204 * Whatever the initialization returned is passed back to the
205 * user level code for further interpretation. We just exit if
206 * it is non-zero since something went wrong.
208 /* this should perform error checking */
209 pthread_mutex_lock(&p->mutex);
210 p->nal_flags |= (rc != PTL_OK) ? NAL_FLAG_STOPPED : NAL_FLAG_RUNNING;
211 pthread_cond_broadcast(&p->cond);
212 pthread_mutex_unlock(&p->mutex);
215 /* the thunk function is called each time the timer loop
216 performs an operation and returns to blocking mode. we
217 overload this function to inform the api side that
218 it may be interested in looking at the event queue */
219 register_thunk(check_stopping,b);