1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*	Copyright (c) 1988 AT&T	*/
28/*	  All Rights Reserved  	*/
29
30#pragma ident	"@(#)newdata.c	1.13	08/05/31 SMI"
31
32#include "libelf.h"
33#include "decl.h"
34#include "msg.h"
35
36
37Elf_Data *
38elf_newdata(Elf_Scn * s)
39{
40	Dnode *		d;
41	Elf_Data *	rc;
42	Elf *		elf;
43	unsigned	work;
44
45	if (s == 0)
46		return (0);
47	elf = s->s_elf;
48	READLOCKS(elf, s)
49	if (s->s_index == SHN_UNDEF) {
50		_elf_seterr(EREQ_SCNNULL, 0);
51		READUNLOCKS(elf, s)
52		return (0);
53	}
54
55	if ((s->s_myflags & SF_READY) == 0) {
56		UPGRADELOCKS(elf, s)
57		/*
58		 * re-confirm that another 'thread' hasn't come along
59		 * and cooked this section while the locks were
60		 * obtained.
61		 */
62		if ((s->s_myflags & SF_READY) == 0)
63			(void) _elf_cookscn(s);
64		DOWNGRADELOCKS(elf, s)
65	}
66
67	/*
68	 * If this is the first new node, use the one allocated
69	 * in the scn itself.  Update data buffer in both cases.
70	 */
71	ELFACCESSDATA(work, _elf_work)
72	if (s->s_hdnode == 0) {
73		s->s_dnode.db_uflags |= ELF_F_DIRTY;
74		s->s_dnode.db_myflags |= DBF_READY;
75		s->s_hdnode = &s->s_dnode;
76		s->s_tlnode = &s->s_dnode;
77		s->s_dnode.db_scn = s;
78		s->s_dnode.db_data.d_version = work;
79		rc = &s->s_dnode.db_data;
80		READUNLOCKS(elf, s)
81		return (rc);
82	}
83	if ((d = _elf_dnode()) == 0) {
84		READUNLOCKS(elf, s)
85		return (0);
86	}
87	NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*d))
88	d->db_data.d_version = work;
89	d->db_scn = s;
90	d->db_uflags |= ELF_F_DIRTY;
91	d->db_myflags |= DBF_READY;
92	s->s_tlnode->db_next = d;
93	s->s_tlnode = d;
94	rc = &d->db_data;
95	NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*d))
96	READUNLOCKS(elf, s)
97	return (rc);
98}
99