static void free_stmt(PLpgSQL_stmt *stmt) { switch ((enum PLpgSQL_stmt_types) stmt->cmd_type) { case PLPGSQL_STMT_BLOCK: free_block((PLpgSQL_stmt_block *) stmt); break; case PLPGSQL_STMT_ASSIGN: free_assign((PLpgSQL_stmt_assign *) stmt); break; case PLPGSQL_STMT_IF: free_if((PLpgSQL_stmt_if *) stmt); break; case PLPGSQL_STMT_CASE: free_case((PLpgSQL_stmt_case *) stmt); break; case PLPGSQL_STMT_LOOP: free_loop((PLpgSQL_stmt_loop *) stmt); break; case PLPGSQL_STMT_WHILE: free_while((PLpgSQL_stmt_while *) stmt); break; case PLPGSQL_STMT_FORI: free_fori((PLpgSQL_stmt_fori *) stmt); break; case PLPGSQL_STMT_FORS: free_fors((PLpgSQL_stmt_fors *) stmt); break; case PLPGSQL_STMT_FORC: free_forc((PLpgSQL_stmt_forc *) stmt); break; case PLPGSQL_STMT_FOREACH_A: free_foreach_a((PLpgSQL_stmt_foreach_a *) stmt); break; case PLPGSQL_STMT_EXIT: free_exit((PLpgSQL_stmt_exit *) stmt); break; case PLPGSQL_STMT_RETURN: free_return((PLpgSQL_stmt_return *) stmt); break; case PLPGSQL_STMT_RETURN_NEXT: free_return_next((PLpgSQL_stmt_return_next *) stmt); break; case PLPGSQL_STMT_RETURN_QUERY: free_return_query((PLpgSQL_stmt_return_query *) stmt); break; case PLPGSQL_STMT_RAISE: free_raise((PLpgSQL_stmt_raise *) stmt); break; case PLPGSQL_STMT_ASSERT: free_assert((PLpgSQL_stmt_assert *) stmt); break; case PLPGSQL_STMT_EXECSQL: free_execsql((PLpgSQL_stmt_execsql *) stmt); break; case PLPGSQL_STMT_DYNEXECUTE: free_dynexecute((PLpgSQL_stmt_dynexecute *) stmt); break; case PLPGSQL_STMT_DYNFORS: free_dynfors((PLpgSQL_stmt_dynfors *) stmt); break; case PLPGSQL_STMT_GETDIAG: free_getdiag((PLpgSQL_stmt_getdiag *) stmt); break; case PLPGSQL_STMT_OPEN: free_open((PLpgSQL_stmt_open *) stmt); break; case PLPGSQL_STMT_FETCH: free_fetch((PLpgSQL_stmt_fetch *) stmt); break; case PLPGSQL_STMT_CLOSE: free_close((PLpgSQL_stmt_close *) stmt); break; case PLPGSQL_STMT_PERFORM: free_perform((PLpgSQL_stmt_perform *) stmt); break; default: elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type); break; } }
/* * msg_connect() * Given a global ID, connect to that port * * TBD: think about allowing connects to be interrupted. It makes * for some hellishly complex state transitions as you race with * the server. */ port_t msg_connect(port_name arg_port, uint arg_mode) { struct proc *p = curthread->t_proc; int slot; struct portref *pr; struct port *port; int error = 0; struct sysmsg sm; /* * Allocate a portref data structure, set it up */ pr = alloc_portref(); /* * Set up nodup flag now while it's safe */ if (arg_mode & ACC_NOCLONE) { pr->p_flags |= PF_NODUP; arg_mode &= ~ACC_NOCLONE; } /* * Allocate a system message, fill it in. */ sm.sm_op = M_CONNECT; sm.sm_sender = pr; sm.sm_seg[0] = (void *)(p->p_ids); sm.sm_nseg = 0; sm.sm_arg = arg_mode; sm.sm_arg1 = sizeof(p->p_ids); /* * Get an open slot */ if ((slot = alloc_open(p)) < 0) { error = -1; goto out; } /* * Now lock name semaphore, and look up our port */ p_sema(&name_sema, PRIHI); port = hash_lookup(portnames, arg_port); if (!port) { v_sema(&name_sema); error = err(ESRCH); goto out; } /* * Lock port */ p_lock_void(&port->p_lock, SPLHI); /* * Fill in port we're trying to attach */ pr->p_port = port; /* * Free up semaphores we don't need to hold any more */ v_sema(&name_sema); /* * Queue our message onto the server's queue, kick him awake */ lqueue_msg(port, &sm); /* * Release lock and fall asleep on our own semaphore */ p_sema_v_lock(&pr->p_iowait, PRIHI, &port->p_lock); /* * If p_port went away, we raced with him closing */ if (!pr->p_port) { error = err(EIO); } /* * If p_state hasn't been set to IODONE, then the connect failed. * The reason has been placed in m_err field of our sysmsg. */ else if (pr->p_state != PS_IODONE) { error = err(sm.sm_err); } /* * If no error, move port state to PS_IODONE and let * it go into service */ if (error == 0) { p->p_open[slot] = pr; error = slot; pr = 0; /* So not freed below */ slot = -1; } /* * All done. Release references as needed, return */ out: if (slot >= 0) { free_open(p, slot); } if (pr) { FREE(pr, MT_PORTREF); } return(error); }