nsalloc.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:13k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*******************************************************************************
  2.  *
  3.  * Module Name: nsalloc - Namespace allocation and deletion utilities
  4.  *              $Revision: 60 $
  5.  *
  6.  ******************************************************************************/
  7. /*
  8.  *  Copyright (C) 2000, 2001 R. Byron Moore
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23.  */
  24. #include "acpi.h"
  25. #include "acnamesp.h"
  26. #include "acinterp.h"
  27. #define _COMPONENT          ACPI_NAMESPACE
  28.  MODULE_NAME         ("nsalloc")
  29. /*******************************************************************************
  30.  *
  31.  * FUNCTION:    Acpi_ns_create_node
  32.  *
  33.  * PARAMETERS:  Acpi_name       - Name of the new node
  34.  *
  35.  * RETURN:      None
  36.  *
  37.  * DESCRIPTION: Create a namespace node
  38.  *
  39.  ******************************************************************************/
  40. acpi_namespace_node *
  41. acpi_ns_create_node (
  42. u32                     name)
  43. {
  44. acpi_namespace_node     *node;
  45. FUNCTION_TRACE ("Ns_create_node");
  46. node = ACPI_MEM_CALLOCATE (sizeof (acpi_namespace_node));
  47. if (!node) {
  48. return_PTR (NULL);
  49. }
  50. ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_allocated++);
  51. node->data_type      = ACPI_DESC_TYPE_NAMED;
  52. node->name           = name;
  53. node->reference_count = 1;
  54. return_PTR (node);
  55. }
  56. /*******************************************************************************
  57.  *
  58.  * FUNCTION:    Acpi_ns_delete_node
  59.  *
  60.  * PARAMETERS:  Node            - Node to be deleted
  61.  *
  62.  * RETURN:      None
  63.  *
  64.  * DESCRIPTION: Delete a namespace node
  65.  *
  66.  ******************************************************************************/
  67. void
  68. acpi_ns_delete_node (
  69. acpi_namespace_node     *node)
  70. {
  71. acpi_namespace_node     *parent_node;
  72. acpi_namespace_node     *prev_node;
  73. acpi_namespace_node     *next_node;
  74. FUNCTION_TRACE_PTR ("Ns_delete_node", node);
  75. parent_node = acpi_ns_get_parent_object (node);
  76. prev_node = NULL;
  77. next_node = parent_node->child;
  78. while (next_node != node) {
  79. prev_node = next_node;
  80. next_node = prev_node->peer;
  81. }
  82. if (prev_node) {
  83. prev_node->peer = next_node->peer;
  84. if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {
  85. prev_node->flags |= ANOBJ_END_OF_PEER_LIST;
  86. }
  87. }
  88. else {
  89. parent_node->child = next_node->peer;
  90. }
  91. ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_freed++);
  92. /*
  93.  * Detach an object if there is one
  94.  */
  95. if (node->object) {
  96. acpi_ns_detach_object (node);
  97. }
  98. ACPI_MEM_FREE (node);
  99. return_VOID;
  100. }
  101. /*******************************************************************************
  102.  *
  103.  * FUNCTION:    Acpi_ns_install_node
  104.  *
  105.  * PARAMETERS:  Walk_state      - Current state of the walk
  106.  *              Parent_node     - The parent of the new Node
  107.  *              Node            - The new Node to install
  108.  *              Type            - ACPI object type of the new Node
  109.  *
  110.  * RETURN:      None
  111.  *
  112.  * DESCRIPTION: Initialize a new entry within a namespace table.
  113.  *
  114.  ******************************************************************************/
  115. void
  116. acpi_ns_install_node (
  117. acpi_walk_state         *walk_state,
  118. acpi_namespace_node     *parent_node,   /* Parent */
  119. acpi_namespace_node     *node,          /* New Child*/
  120. acpi_object_type8       type)
  121. {
  122. u16                     owner_id = TABLE_ID_DSDT;
  123. acpi_namespace_node     *child_node;
  124. FUNCTION_TRACE ("Ns_install_node");
  125. /*
  126.  * Get the owner ID from the Walk state
  127.  * The owner ID is used to track table deletion and
  128.  * deletion of objects created by methods
  129.  */
  130. if (walk_state) {
  131. owner_id = walk_state->owner_id;
  132. }
  133. /* link the new entry into the parent and existing children */
  134. /* TBD: Could be first, last, or alphabetic */
  135. child_node = parent_node->child;
  136. if (!child_node) {
  137. parent_node->child = node;
  138. }
  139. else {
  140. while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) {
  141. child_node = child_node->peer;
  142. }
  143. child_node->peer = node;
  144. /* Clear end-of-list flag */
  145. child_node->flags &= ~ANOBJ_END_OF_PEER_LIST;
  146. }
  147. /* Init the new entry */
  148. node->owner_id  = owner_id;
  149. node->flags     |= ANOBJ_END_OF_PEER_LIST;
  150. node->peer      = parent_node;
  151. /*
  152.  * If adding a name with unknown type, or having to
  153.  * add the region in order to define fields in it, we
  154.  * have a forward reference.
  155.  */
  156. if ((ACPI_TYPE_ANY == type) ||
  157. (INTERNAL_TYPE_FIELD_DEFN == type) ||
  158. (INTERNAL_TYPE_BANK_FIELD_DEFN == type)) {
  159. /*
  160.  * We don't want to abort here, however!
  161.  * We will fill in the actual type when the
  162.  * real definition is found later.
  163.  */
  164. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "[%4.4s] is a forward referencen",
  165. (char*)&node->name));
  166. }
  167. /*
  168.  * The Def_field_defn and Bank_field_defn cases are actually
  169.  * looking up the Region in which the field will be defined
  170.  */
  171. if ((INTERNAL_TYPE_FIELD_DEFN == type) ||
  172. (INTERNAL_TYPE_BANK_FIELD_DEFN == type)) {
  173. type = ACPI_TYPE_REGION;
  174. }
  175. /*
  176.  * Scope, Def_any, and Index_field_defn are bogus "types" which do
  177.  * not actually have anything to do with the type of the name
  178.  * being looked up.  Save any other value of Type as the type of
  179.  * the entry.
  180.  */
  181. if ((type != INTERNAL_TYPE_SCOPE) &&
  182. (type != INTERNAL_TYPE_DEF_ANY) &&
  183. (type != INTERNAL_TYPE_INDEX_FIELD_DEFN)) {
  184. node->type = (u8) type;
  185. }
  186. ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%4.4s added to %p at %pn",
  187. (char*)&node->name, parent_node, node));
  188. /*
  189.  * Increment the reference count(s) of all parents up to
  190.  * the root!
  191.  */
  192. while ((node = acpi_ns_get_parent_object (node)) != NULL) {
  193. node->reference_count++;
  194. }
  195. return_VOID;
  196. }
  197. /*******************************************************************************
  198.  *
  199.  * FUNCTION:    Acpi_ns_delete_children
  200.  *
  201.  * PARAMETERS:  Parent_node     - Delete this objects children
  202.  *
  203.  * RETURN:      None.
  204.  *
  205.  * DESCRIPTION: Delete all children of the parent object. Deletes a
  206.  *              "scope".
  207.  *
  208.  ******************************************************************************/
  209. void
  210. acpi_ns_delete_children (
  211. acpi_namespace_node     *parent_node)
  212. {
  213. acpi_namespace_node     *child_node;
  214. acpi_namespace_node     *next_node;
  215. u8                      flags;
  216. FUNCTION_TRACE_PTR ("Ns_delete_children", parent_node);
  217. if (!parent_node) {
  218. return_VOID;
  219. }
  220. /* If no children, all done! */
  221. child_node = parent_node->child;
  222. if (!child_node) {
  223. return_VOID;
  224. }
  225. /*
  226.  * Deallocate all children at this level
  227.  */
  228. do {
  229. /* Get the things we need */
  230. next_node   = child_node->peer;
  231. flags       = child_node->flags;
  232. /* Grandchildren should have all been deleted already */
  233. if (child_node->child) {
  234. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Found a grandchild! P=%p C=%pn",
  235. parent_node, child_node));
  236. }
  237. /* Now we can free this child object */
  238. ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_freed++);
  239. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Object %p, Remaining %Xn",
  240. child_node, acpi_gbl_current_node_count));
  241. /*
  242.  * Detach an object if there is one, then free the child node
  243.  */
  244. acpi_ns_detach_object (child_node);
  245. ACPI_MEM_FREE (child_node);
  246. /* And move on to the next child in the list */
  247. child_node = next_node;
  248. } while (!(flags & ANOBJ_END_OF_PEER_LIST));
  249. /* Clear the parent's child pointer */
  250. parent_node->child = NULL;
  251. return_VOID;
  252. }
  253. /*******************************************************************************
  254.  *
  255.  * FUNCTION:    Acpi_ns_delete_namespace_subtree
  256.  *
  257.  * PARAMETERS:  Parent_node     - Root of the subtree to be deleted
  258.  *
  259.  * RETURN:      None.
  260.  *
  261.  * DESCRIPTION: Delete a subtree of the namespace.  This includes all objects
  262.  *              stored within the subtree.  Scope tables are deleted also
  263.  *
  264.  ******************************************************************************/
  265. acpi_status
  266. acpi_ns_delete_namespace_subtree (
  267. acpi_namespace_node     *parent_node)
  268. {
  269. acpi_namespace_node     *child_node = NULL;
  270. u32                     level = 1;
  271. FUNCTION_TRACE ("Ns_delete_namespace_subtree");
  272. if (!parent_node) {
  273. return_ACPI_STATUS (AE_OK);
  274. }
  275. /*
  276.  * Traverse the tree of objects until we bubble back up
  277.  * to where we started.
  278.  */
  279. while (level > 0) {
  280. /* Get the next node in this scope (NULL if none) */
  281. child_node = acpi_ns_get_next_node (ACPI_TYPE_ANY, parent_node,
  282.  child_node);
  283. if (child_node) {
  284. /* Found a child node - detach any attached object */
  285. acpi_ns_detach_object (child_node);
  286. /* Check if this node has any children */
  287. if (acpi_ns_get_next_node (ACPI_TYPE_ANY, child_node, 0)) {
  288. /*
  289.  * There is at least one child of this node,
  290.  * visit the node
  291.  */
  292. level++;
  293. parent_node   = child_node;
  294. child_node    = 0;
  295. }
  296. }
  297. else {
  298. /*
  299.  * No more children of this parent node.
  300.  * Move up to the grandparent.
  301.  */
  302. level--;
  303. /*
  304.  * Now delete all of the children of this parent
  305.  * all at the same time.
  306.  */
  307. acpi_ns_delete_children (parent_node);
  308. /* New "last child" is this parent node */
  309. child_node = parent_node;
  310. /* Move up the tree to the grandparent */
  311. parent_node = acpi_ns_get_parent_object (parent_node);
  312. }
  313. }
  314. return_ACPI_STATUS (AE_OK);
  315. }
  316. /*******************************************************************************
  317.  *
  318.  * FUNCTION:    Acpi_ns_remove_reference
  319.  *
  320.  * PARAMETERS:  Node           - Named node whose reference count is to be
  321.  *                               decremented
  322.  *
  323.  * RETURN:      None.
  324.  *
  325.  * DESCRIPTION: Remove a Node reference.  Decrements the reference count
  326.  *              of all parent Nodes up to the root.  Any node along
  327.  *              the way that reaches zero references is freed.
  328.  *
  329.  ******************************************************************************/
  330. static void
  331. acpi_ns_remove_reference (
  332. acpi_namespace_node     *node)
  333. {
  334. acpi_namespace_node     *next_node;
  335. FUNCTION_ENTRY ();
  336. /*
  337.  * Decrement the reference count(s) of this node and all
  338.  * nodes up to the root,  Delete anything with zero remaining references.
  339.  */
  340. next_node = node;
  341. while (next_node) {
  342. /* Decrement the reference count on this node*/
  343. next_node->reference_count--;
  344. /* Delete the node if no more references */
  345. if (!next_node->reference_count) {
  346. /* Delete all children and delete the node */
  347. acpi_ns_delete_children (next_node);
  348. acpi_ns_delete_node (next_node);
  349. }
  350. /* Move up to parent */
  351. next_node = acpi_ns_get_parent_object (next_node);
  352. }
  353. }
  354. /*******************************************************************************
  355.  *
  356.  * FUNCTION:    Acpi_ns_delete_namespace_by_owner
  357.  *
  358.  * PARAMETERS:  Owner_id    - All nodes with this owner will be deleted
  359.  *
  360.  * RETURN:      Status
  361.  *
  362.  * DESCRIPTION: Delete entries within the namespace that are owned by a
  363.  *              specific ID.  Used to delete entire ACPI tables.  All
  364.  *              reference counts are updated.
  365.  *
  366.  ******************************************************************************/
  367. acpi_status
  368. acpi_ns_delete_namespace_by_owner (
  369. u16                     owner_id)
  370. {
  371. acpi_namespace_node     *child_node;
  372. u32                     level;
  373. acpi_namespace_node     *parent_node;
  374. FUNCTION_TRACE ("Ns_delete_namespace_by_owner");
  375. parent_node = acpi_gbl_root_node;
  376. child_node  = 0;
  377. level       = 1;
  378. /*
  379.  * Traverse the tree of nodes until we bubble back up
  380.  * to where we started.
  381.  */
  382. while (level > 0) {
  383. /* Get the next node in this scope (NULL if none) */
  384. child_node = acpi_ns_get_next_node (ACPI_TYPE_ANY, parent_node,
  385.  child_node);
  386. if (child_node) {
  387. if (child_node->owner_id == owner_id) {
  388. /* Found a child node - detach any attached object */
  389. acpi_ns_detach_object (child_node);
  390. }
  391. /* Check if this node has any children */
  392. if (acpi_ns_get_next_node (ACPI_TYPE_ANY, child_node, 0)) {
  393. /*
  394.  * There is at least one child of this node,
  395.  * visit the node
  396.  */
  397. level++;
  398. parent_node   = child_node;
  399. child_node    = 0;
  400. }
  401. else if (child_node->owner_id == owner_id) {
  402. acpi_ns_remove_reference (child_node);
  403. }
  404. }
  405. else {
  406. /*
  407.  * No more children of this parent node.
  408.  * Move up to the grandparent.
  409.  */
  410. level--;
  411. if (level != 0) {
  412. if (parent_node->owner_id == owner_id) {
  413. acpi_ns_remove_reference (parent_node);
  414. }
  415. }
  416. /* New "last child" is this parent node */
  417. child_node = parent_node;
  418. /* Move up the tree to the grandparent */
  419. parent_node = acpi_ns_get_parent_object (parent_node);
  420. }
  421. }
  422. return_ACPI_STATUS (AE_OK);
  423. }